一、初始化项目
二、配置主要的属性
三、解析过程
四、解析样式文件
1、解析css
module: {rules: [{test: /\.css$/,// 多个loader是有顺序的,从右往左写,转换的时候是从右往左进行转换的loader: ['style-loader', 'css-loader'],// css-loader:用来解析处理css文件中的url路径// style-loader:可以把css文件变成style标签插入到header中}]}
2、将css文件中bundle.js中分离出来
const MiniCssExtractPlugin = require("mini-css-extract-plugin");module: {rules: [{test: /\.css$/,use: [{loader:MiniCssExtractPlugin.loader,options:{publicPath:'../'}},"css-loader"]}]}plugins: [new MiniCssExtractPlugin({filename: "[name].css",chunkFilename: "[id].css"})]
3、提取css文件到单独文件夹中
plugins: [new MiniCssExtractPlugin({filename: "css/[name].css",chunkFilename: "[id].css"})]// 提取css文件到css文件夹中
4、压缩css样式文件
去除空格、换行
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");plugins: [new OptimizeCSSAssetsPlugin({})]
5、解析scss
6、处理css前缀
7、问题总结
- 提取css文件插件更换(’extract-text-webpack-plugin’换成’mini-css-extract-plugin’)
- 压缩写法变化
五、通过插件生成html
```javascript const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
plugins: [ new HtmlWebpackPlugin({ template: ‘./src/index.html’, // 以该html文件为模板,生成文件 filename: ‘index.html’ // 产生后的文件名 }) ]
<a name="lmXzo"></a>## 六、打包前清除dist文件夹```javascriptconst {CleanWebpackPlugin} = require('clean-webpack-plugin');new CleanWebpackPlugin()/*注意:const CleanWebpackPlugin = require('clean-webpack-plugin'); 错误写法new CleanWebpackPlugin(['dist']) 错误写法,新版本不需要指定文件夹名称会自动根据出入的文件名进行删除,并重新打包创建*/
七、解析ES6
解析es6需要用到babel。
babel转义靠的就是AST(抽象语法树)
npm install --save-dev babel-loader @babel/corenpm install @babel/preset-env --save-devhttps://juejin.im/post/6844904181501952014
1、压缩js
const uglify = require('uglifyjs-webpack-plugin');new uglify()
八、解析图片和字体
1、通过js new Image()let src = require('./img/1.png')let img = new Image()img.src = srcdocument.body.appendChild(img)rules: [{// file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置test: /\.(png|jpg|gif|svg|bmp)/,use: 'file-loader'}]2、在css中当成背景图引入3、通过img标签引入需要html-widthimg-loader -D
把图片打包到固定的文件夹目录下
rules: [{// file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置test: /\.(png|jpg|gif|svg|bmp)/,use: {loader: 'file-loader',// 指定拷贝文件的输出目录options: {outputPath: 'images/'}}}]
将比较小的图标打包成base64格式,嵌到页面中,这样就能减少一次资源请求了。
rules: [{// file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置test: /\.(png|jpg|gif|svg|bmp)/,use: {loader: 'url-loader',// 指定拷贝文件的输出目录options: {limit: 9 * 1024, // 小于9kb一下的 就打包成base64outputPath: 'images/'}}}]
九、配置多页开发
// 先找到每个入口(entry),然后从各个入口分别处罚,找到依赖的模块(module)// 然后生成一个chunk(代码块)(一个代码块包含很多模块)最后会把chunk写到文件系统中(assets)entry: {index: './src/index.js',base: './src/base.js'}plugins: [new HtmlWebpackPlugin({template: './src/index.html', // 以该html文件为模板,生成文件filename: 'index.html', // 产生后的文件名chunk: ['index']}),new HtmlWebpackPlugin({template: './src/index.html', // 以该html文件为模板,生成文件filename: 'base.html', // 产生后的文件名chunk: ['base']})]// 如果页面过多,不可能一直写HtmlWebpackPlugin,可以写for循环
十、公共库的打包
我们模块中使用了公共库,我们不应该把库文件打包到bundle中,这样的话,bundle文件太大。
1、提取公共库文件
cnpm install jquery -Sconst $ = require('jquery')console.log($)
打包之后:
const webpack = require('webpack');plugin: [// 全局下都可以使用$代表jquerynew webpack.ProvidePlugin({$: 'jquery'})],// 提取公共模块,包括第三方库和自定义工具库等optimization: {// 找到chunk中共享的模块,取出来生成单独的chunksplitChunks: {chunks: "all", // async表示抽取异步模块,all表示对所有模块生效,initial表示对同步模块生效cacheGroups: {vendors: { // 抽离第三方插件test: /[\\/]node_modules[\\/]/, // 指定是node_modules下的第三方包name: "vendors",priority: -10 // 抽取优先级},utilCommon: { // 抽离自定义工具库name: "common",minSize: 0, // 将引用模块分离成新代码文件的最小体积minChunks: 2, // 表示将引用模块如不同文件引用了多少次,才能分离生成新chunkpriority: -20}}},// 为 webpack 运行时代码创建单独的chunkruntimeChunk:{name:'manifest'}}
十一、配置别名
reolsve: {alias: { // 别名"@": './src'},// 命中率高的往前写,命中率低的往后写extensions: ['', '.js', '.json'] // 配置扩展名(引入模块的时候,可以不加扩展名)}
十二、优化方案
1、缩小文件搜索范围
// 当你引入一个模块的时候,要进行解析resolve: {// 当你需要指定node_modules之外的其他模块目录的话modules: [path.resolve(__dirname, 'node_modules')],alias: {// 当加载react模块的时候,react: path.resolve('./cjs/react.production.min.js')}}
2、noParse 不处理的模块
module.noParse配置可以让webpack忽略对部分没采用慕课话的文件的递归解析处理
module: {noParse: [/react\.min\.js/]}被忽略掉的文件里不应该包含import require define等模块化语句
// 如果打包的文件过大rules: [{test: /\.jsx?$/,use: [{loader: 'babel-loader'}],// 只转换或者编译src目录下的文件include: path.resolve('./src'),// 排除node_modulesexclude: /node_modules/}]
noParse减少打包查询时间,也可以减少打包文件的大小。从而提高构建性能。
3、DLL
.dll为后缀的文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据。
- 把基础模块独立处理打包到单独的动态链接库里
- 当需要导入的模块在动态链接库里的时候,模块不能再次被打包,而是去动态链接库里获取dll-plugin
1、定义DLL
- DllPlugin插件:用于打包一个个动态链接库
- DllReferencePlugin:在配置文件中引入DllPlugin插件打包好的动态链接库
4、优化loader的配置
通过include去命中 只有哪些文件去处理,通过exclude去除哪些文件不需要处理,例如node_module5、优化resolve.modules配置
resolve.modules用于配置Webpack去哪些目录下寻找第三方模块。resolve.modelus的默认值是['node_modules']含义是先去当前目录的./node_modules目录下去找我们想找的模块,如果没找到,就去上一级目录../node_modules中找,再没有就去../../node_modules中找,以此类推当安装的第三方模块都放在项目根目录的./node_modules目录下时,就没有必要按照默认的方式去一层层的寻找,可以指明存放第三方模块的绝对路径,以减少寻找,配置如下:module.exports = {resolve: {// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤// 其中,__dirname表示当前工作目录,也就是项目根目录modules: [path.resolve(__dirname,'node_modules')]}}
6、优化resolve.alias配置,跳过递归解析操作
7、优化resolve.extensions配置
减少后缀,后缀尽可能的少,这样能提升打包速度,减少打包时间8、ParallelUglifyPlugin
原本会使用Uglifyjs去一个一个压缩再输出
Paralleuglifyplugin会开启多个子线程,将对多个文件的压缩工作分配给多个子进程完成,每个子进程其实还是通过uglify去压缩代码,但是变成了并行执行,所以Paralleuglifyplugin能更快地完成对多个文件的压缩工作9、利用缓存提升二次构建速度
十三、webpack-dev-server
webpack-dev-server打包后的文件,放到了内存中,所以我们在本地文件夹中是看不到的十四、npm 和 npx的区别
npx可以执行命令(.bin目录下的命令,npm无法执行)
npm只能执行脚本命令十五、监控源文件的变化
// 表示监控源文件的变化,当源文件发售改变后,则重新打包watch: true,watchOptions: {exclude/ignored: /node_modules/,poll: 1000, // 每秒中询问的次数aggregateTimeout: 500, //}
十六、文件拷贝
一些不需要打包的依赖文件,需要同时拷贝过去 ```javascript copy-webpack-plugin
const CopyWebpackPlugin = require(‘copy-webpack-plugin’) plugins: [ new CopyWebpackPlugin([{ form: path.join(dirname, ‘public’), to: path.join(dirname, ‘dist’) }]) ]
<a name="aSAzy"></a>## 十七、自动更新<a name="H2zNI"></a>## 十八、区分环境<a name="3tXUo"></a>## 十九、配置CDN<a name="ZvOdB"></a>## 二十、Tree-shaking前端中的tree-shaking可以理解为通过工具"摇"我们的JS文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。具体来说,在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。<br />Tree-shaking的本质是消除无用的js代码。无用代码消除在广泛存在于传统的编程语言编译器中,编译器可以判断出某些代码根本不影响输出,然后消除这些代码,这个称之为DCE(dead code elimination)。<br />Tree-shaking 是 DCE 的一种新的实现,Javascript同传统的编程语言不同的是,javascript绝大多数情况需要通过网络进行加载,然后执行,加载的文件大小越小,整体执行时间更短,所以去除无用代码以减少文件体积,对javascript来说更有意义。<a name="xRzXh"></a>## 二十一、开启Scope Hoisting是webpack3推出的新功能,直译”作用域提升“,他可以让webpack打包出来的代码文件更小,运行更快。<br />webpack将引入的js文件提升大屏它的引入者的顶部```javascript// main.jsexport default "hello leo~";// index.jsimport str from "./main.js";
开启和不开启打包的文件大小不一样。
好处:
- 代码体积更小,因为函数声明语句中会产生大量代码,导致包的体积增大
- 代码在运行时会因为创建的函数作用域更少,内存开销也会变小
1、原理
Scope Hoisting 的实现原理其实很简单:分析出模块之间的依赖关系,尽可能将打散的模块合并到一个函数中,前提是不能造成代码冗余。 因此只有那些被引用了一次的模块才能被合并。2、使用
1、webpack在mode为production时,会默认启用Scope Hoisting
2、手动
配置ModuleConcatenationPlugin插件new webpack.optimize.ModuleConcatenationPlugin();
二十二、代码分离
二十三、懒加载

