创建webpackl配置文件
(配置文件是在打包过程中会运行,打包的那些文件不会运行,所以是在node环境中运行的)
webpack.config.js
只要最终导出一个对象就行(只能用commonJs导出)
mode 模式 {development开发环境 production运行环境}
entry 入口 entry:“path” (字符串)
配置项
{
mainTest: “./src/index.js”, //属性名chunk的名称, 属性值:入口模块(启动模块)
secondTest: “./src/a.js”, //属性名chunk的名称, 属性值:入口模块(启动模块)
//如果配置多个入口,这样出口的名称也要动态生成
},
output 出口 配置出口默认就是dist里面的manin.js (对象)
配置项
{
path: path.resolve(__dirname, “target”), //必须是一个绝对路径,表示资源放置的文件夹
filename: “bundle.js”, //配置的合并的js文件的规则
filename: “[name].js”, //适应多个入口 name是webpack可以在官网查看更多配置
},
devtool //配置源码地图 sourceMap
module //配置loader对匹配到的模块进行重新改变
配置项
rules: [
{
test: /index.js/, //模块匹配的规则
use: [
{
loader: “./loader/test-loader.js?changeVar=‘未知数’”, //用哪个loader进行解析,后面是下面options里面的配置也可以直接写在后面
options: {
//配置项 可以保存在this对象中,可以在loader中用this.loader.xxx获取
changeVar: “未知数”,
},
},
],
},
], //那些模块要被loader加工的规则
// noParse: {}, //那些东西(例如正则)不要被loader解析
编写一个cssLoader为什么不能直接导入css文件,因为css文件不能被解析成抽象语法输(AST),所以打包会报错cssLoader只要把css代码转换成js代码,(打包不会运行需要打包的代码)
module.exports = function (sourceCode) {
var style = `var style = document.createElement("style");
style.innerHTML = \`${sourceCode}\`;
document.head.appendChild(style);
module.exports=\`${sourceCode}\``;
return style;
};
plugin 插件
plugin的本质是一个带有apply方法的对象
可以写成一个构造函数
module.exports = class myPlugin {
apply(compiler) {
console.log("plugin运行了");
compiler.hooks.done.tap("myPlugin", function (compilation) {
//compiler.hooks 表示创建一个事件监听
//done事件类型
//tap 那边有三个可选参数
// - tap:注册一个同步的钩子函数,函数运行完毕则表示事件处理结束
// - tapAsync:注册一个基于回调的异步的钩子函数,函数通过调用一个回调表示事件处理结束
// - tapPromise:注册一个基于Promise的异步的钩子函数,函数通过返回的Promise进入已决状态表示事件处理结束
//name 函数的名字
//function 回调函数,事件处理函数
});
//如果要注册compilation的事件的话要触发compiler的beforeRun事件拿到compilation对象之后再去注册
// compiler.hooks.beforeRun.tap("myPlugin", function (compilation) {
// compilation.hooks.XXX;
// });
}
};
//调用
plugins: [new myPlugin()],
在编写插件时apply中传入一个参数compiler
apply函数会在初始化阶段,创建好Compiler对象后运行。
compiler对象是在初始化阶段构建的,整个webpack打包期间只有一个compiler对象,后续完成打包工作的是compiler对象内部创建的compilation
apply方法会在创建好compiler对象后调用,并向方法传入一个compiler对象
fileListPlugin示例 获取文件的名字及大小
plugins: [new fileListPlugin("filename.text")]
//引入插件
module.exports = class fileListPlugin {
//可以在使用插件的时候传值
constructor(filename = "fileList.text") {
this.filename = filename;
}
apply(compiler) {
compiler.hooks.emit.tap("fileListPlugin", (compilation) => {
let fileList = [];
//compilation.assets 打包完后所有文件对象
for (const key in compilation.assets) {
let content = "";
if (Object.hasOwnProperty.call(compilation.assets, key)) {
content = `${key}
${compilation.assets[key].size() / 1024}kb`; // 获取哪个文件
fileList.push(content); // 保存在一个数组里
}
}
var str = fileList.join("\n");
compilation.assets[this.filename] = {
//可以在使用插件的时候传值
//添加一个fileList.text文件
source() {
//写入内容
return str;
},
size() {
// 文件大小
return str.length;
},
};
});
}
};