本帖最后由 长沙-小知姐姐 于 2020-4-28 15:44 编辑
需要视频笔记源码的朋友可以回帖获取网盘密码(如失效请联系vx:csheima7) https://pan.baidu.com/s/1J2QCSy1d7lbQh4uFjAKG-w jj4w
###1.webpack的概念 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
通俗的来说,webpack就是一个打包构建工具,将各种各样的资源整合打包到一起,形成一个最终的完整项目。
###2.webpack的基本配置 ####A.安装webpack npm install webpack webpack-cli -D ####B.在项目目录中创建webpack.config.js文件用来配置webpack 在配置文件中可以配置开发模式和发布模式两种,如下: module.exports = { mode:"development"//可以设置为development(开发模式),production(发布模式) }
也可以在运行webpack命令时,添加参数设置模式,如下: webpack --mode=development
####C.在webpack.config.js文件中通过entry和output来设置入口和出口 ``` const path = require("path"); module.exports = { mode:"development", //设置入口文件路径 entry: path.join(__dirname,"./src/js/index.js"), //设置出口文件 output:{ //设置路径 path:path.join(__dirname,"./dist"), //设置文件名 filename:"bundle.js" } } ```
补充:配置多入口和多出口 ``` const path = require("path"); module.exports = { mode:"development", //设置入口文件路径 entry: { "one":path.join(__dirname,"./src/js/one.js"), "two":path.join(__dirname,"./src/js/one.js") }, //设置出口文件 output:{ //设置路径 path:path.join(__dirname,"./dist"), //设置文件名 filename:"[name].js" } } ```
####D.使用webpack-dev-server自动打包运行项目 第一步,安装webpack-dev-server,安装html-webpack-plugin npm install webpack-dev-server -D npm install html-webpack-plugin -D 第二步,修改package.json文件,配置运行指令 在package.json文件中添加或修改scripts节点,添加一个dev指令 "scripts":{ "dev":"webpack-dev-server --open --host 127.0.0.1 --port 9999" } 第三步,在webpack.config.js文件中添加html-webpack-plugin插件进行项目预览 ``` const HtmlWebpackPlugin = require("html-webpack-plugin"); //创建对象 const htmlPlugin = new HtmlWebpackPlugin({ //设置生成预览页面的模板文件 template:"./src/index.html", //设置生成的预览页面名称 filename:"index.html" }) module.exports = { mode:"development", //设置入口文件路径 entry: path.join(__dirname,"./src/js/index.js"), //设置出口文件 output:{ //设置路径 path:path.join(__dirname,"./dist"), //设置文件名 filename:"index.js" }, // 使用plugins数组添加webpack需要使用的插件 plugins:[ htmlPlugin ] } ```
注意: 无论是修改了package.json还是修改了webpack.config.js,请重启webpack-dev-serve才会让修改的内容生效。
###3.使用加载器预处理文件 加载器loader可以对模块的源代码进行转换。当我们使用import去导入一个文件的时候,加载器会对这个文件进行预处理和转换。 它可以把文件从不同的语言(比如typescript,高级JS语法等)转换成javascript,也可以将图片转换为data URL,甚至可以处理和转换css文件。
一句话,webpack本身只是一个构建工具,它一般只能识别js文件,如果想要让他识别和处理其他类型的文件,我们就需要给他添加功能(加载器)
比如说我们可以安装css的加载器,用来处理css样式,为此我们需要安装css-loader与style-loader,如下: npm install style-loader css-loader -D
加载器的配置使用方式有三种: A.使用配置文件 在webpack.config.js文件中可以通过module.rules配置加载器,如下 ``` module.exports = { mode:"development", //设置入口文件路径 entry: path.join(__dirname,"./src/js/index.js"), //设置出口文件 output:{ //设置路径 path:path.join(__dirname,"./dist"), //设置文件名 filename:"index.js" }, // 通过module.rules配置加载器 module:{ rules:[ //rules是一个数组,可以用来配置多个加载器 //加载器的执行顺序是反向的,也就是说先执行css-load,再执行style-loader { test:/\.css$/, use: ['style-loader','css-loader'] } } } ```
B.使用内联语法 就是编写js代码去引入加载器,使用!隔开多个加载器,使用?拼接参数 ?后面的modules表示的是打开CSS Modules功能,modules后面跟着的是需要引入并处理的index.css文件路径 import Styles from 'style-loader!css-loader?modules!../css/index.css';
C.在命令行中使用加载器 webpack --module-bind 'css=style-loader!css-loader'
小结: B形式会导致导入解析的代码过多,C形式会导致命令的参数过多。 所以一般推荐使用A形式,在配置文件中配置,修改和定位都会更加简单。
###4.自定义loader加载器 Webpack中loader是一个CommonJs风格的函数,接收输入的源码,通过同步或异步的方式替换源码后进行输出。 基本形式如下: module.exports = function(source) { //source是源码 return source.replace(/console/g, '//console') }
然后需要在webpack.config.js中配置自定义loader
###5.webpack插件 插件是 webpack中一个非常重要的功能。插件目的在于解决 loader 无法实现的其他事 自定义插件的步骤: A.创建一个函数 function myPlugin(){
}
B.给函数扩展一个apply方法 //注意,定义的函数不能写作箭头函数形式,否则函数中的this指向将会出错 myPlugin.prototype.apply = function( compiler ){ // compiler是一个对象,包含webpack的所有配置信息,在启动时被初始化,包括entry、output、loaders等配置,这个对象在启动Webpack时被实例化,而且是全局唯一的。Plugin可以通过该对象获取到Webpack的配置信息进行处理 // compilation Compilation对象可以理解编译对象,包含了模块、依赖、文件等信息,每修改一次文件都会产生一个新的Compilation对象,Plugin可以访问到本次编译过程中的模块、依赖、文件内容等信息 compiler.plugin('compile', function (compilationParams) { console.log(compilationParams) console.log('webpack 编译器开始编译...-----') }) }
C.指定webpack的事件钩子 常见的钩子如下:
| 钩子 | 说明 | 参数 | 类型 | | ------------ | ----------------- | ----------------- | ---- | | afterPlugins | 启动一次新的编译 | compiler | 同步 | | compile | 创建compilation对象之前 | compilationParams | 同步 | | compilation | compilation对象创建完成 | compilation | 同步 | | emit | 资源生成完成,输出之前 | compilation | 异步 | | afterEmit | 资源输出到目录完成 | compilation | 异步 | | done | 完成编译 stats | | 同步 |
我们可以使用Tabable暴露的tap,tapAsync和tapPromise方法来调用调用上面的钩子,如下 compiler.hooks.compile.tap('myPlugin', params => { console.log('我是同步钩子') }); compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) => { setTimeout(()=>{ console.log('文件列表', Object.keys(compilation.assets).join(',')); callback(); }, 1000); });
具体的使用案例形式为: function myPlugin(){
} myPlugin.prototype.apply = function( compiler ){ compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) => { // compilation.chunks存放了代码块列表 compilation.chunks.forEach(chunk => { // chunk包含多个模块,通过chunk.modulesIterable可以遍历模块列表 for(const module of chunk.modulesIterable) { // module包含多个依赖,通过module.dependencies进行遍历 module.dependencies.forEach(dependency => { console.log(dependency); }); } }); callback(); }); }
|