一、初始化项目

二、配置主要的属性

三、解析过程

四、解析样式文件

1、解析css

  1. module: {
  2. rules: [
  3. {
  4. test: /\.css$/,
  5. // 多个loader是有顺序的,从右往左写,转换的时候是从右往左进行转换的
  6. loader: ['style-loader', 'css-loader'],
  7. // css-loader:用来解析处理css文件中的url路径
  8. // style-loader:可以把css文件变成style标签插入到header中
  9. }
  10. ]
  11. }

2、将css文件中bundle.js中分离出来

  1. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  2. module: {
  3. rules: [
  4. {
  5. test: /\.css$/,
  6. use: [
  7. {
  8. loader:MiniCssExtractPlugin.loader,
  9. options:{
  10. publicPath:'../'
  11. }
  12. },
  13. "css-loader"
  14. ]
  15. }
  16. ]
  17. }
  18. plugins: [
  19. new MiniCssExtractPlugin({
  20. filename: "[name].css",
  21. chunkFilename: "[id].css"
  22. })
  23. ]

3、提取css文件到单独文件夹中

  1. plugins: [
  2. new MiniCssExtractPlugin({
  3. filename: "css/[name].css",
  4. chunkFilename: "[id].css"
  5. })
  6. ]
  7. // 提取css文件到css文件夹中

4、压缩css样式文件

去除空格、换行

  1. const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
  2. plugins: [
  3. new OptimizeCSSAssetsPlugin({})
  4. ]

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’ // 产生后的文件名 }) ]

  1. <a name="lmXzo"></a>
  2. ## 六、打包前清除dist文件夹
  3. ```javascript
  4. const {CleanWebpackPlugin} = require('clean-webpack-plugin');
  5. new CleanWebpackPlugin()
  6. /*
  7. 注意:
  8. const CleanWebpackPlugin = require('clean-webpack-plugin'); 错误写法
  9. new CleanWebpackPlugin(['dist']) 错误写法,新版本不需要指定文件夹名称
  10. 会自动根据出入的文件名进行删除,并重新打包创建
  11. */

七、解析ES6

解析es6需要用到babel。
babel转义靠的就是AST(抽象语法树)

  1. npm install --save-dev babel-loader @babel/core
  2. npm install @babel/preset-env --save-dev
  3. https://juejin.im/post/6844904181501952014

1、压缩js

  1. const uglify = require('uglifyjs-webpack-plugin');
  2. new uglify()

指标变化:压缩之后,.js文件变小了
image.png
image.png

八、解析图片和字体

  1. 1、通过js new Image()
  2. let src = require('./img/1.png')
  3. let img = new Image()
  4. img.src = src
  5. document.body.appendChild(img)
  6. rules: [{
  7. // file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置
  8. test: /\.(png|jpg|gif|svg|bmp)/,
  9. use: 'file-loader'
  10. }]
  11. 2、在css中当成背景图引入
  12. 3、通过img标签引入
  13. 需要html-widthimg-loader -D

把图片打包到固定的文件夹目录下

  1. rules: [{
  2. // file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置
  3. test: /\.(png|jpg|gif|svg|bmp)/,
  4. use: {
  5. loader: 'file-loader',
  6. // 指定拷贝文件的输出目录
  7. options: {
  8. outputPath: 'images/'
  9. }
  10. }
  11. }]

将比较小的图标打包成base64格式,嵌到页面中,这样就能减少一次资源请求了。

  1. rules: [{
  2. // file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置
  3. test: /\.(png|jpg|gif|svg|bmp)/,
  4. use: {
  5. loader: 'url-loader',
  6. // 指定拷贝文件的输出目录
  7. options: {
  8. limit: 9 * 1024, // 小于9kb一下的 就打包成base64
  9. outputPath: 'images/'
  10. }
  11. }
  12. }]

九、配置多页开发

  1. // 先找到每个入口(entry),然后从各个入口分别处罚,找到依赖的模块(module)
  2. // 然后生成一个chunk(代码块)(一个代码块包含很多模块)最后会把chunk写到文件系统中(assets)
  3. entry: {
  4. index: './src/index.js',
  5. base: './src/base.js'
  6. }
  7. plugins: [
  8. new HtmlWebpackPlugin({
  9. template: './src/index.html', // 以该html文件为模板,生成文件
  10. filename: 'index.html', // 产生后的文件名
  11. chunk: ['index']
  12. }),
  13. new HtmlWebpackPlugin({
  14. template: './src/index.html', // 以该html文件为模板,生成文件
  15. filename: 'base.html', // 产生后的文件名
  16. chunk: ['base']
  17. })
  18. ]
  19. // 如果页面过多,不可能一直写HtmlWebpackPlugin,可以写for循环

十、公共库的打包

我们模块中使用了公共库,我们不应该把库文件打包到bundle中,这样的话,bundle文件太大。

1、提取公共库文件

  1. cnpm install jquery -S
  2. const $ = require('jquery')
  3. console.log($)

打包之后:
image.png

  1. const webpack = require('webpack');
  2. plugin: [
  3. // 全局下都可以使用$代表jquery
  4. new webpack.ProvidePlugin({
  5. $: 'jquery'
  6. })
  7. ],
  8. // 提取公共模块,包括第三方库和自定义工具库等
  9. optimization: {
  10. // 找到chunk中共享的模块,取出来生成单独的chunk
  11. splitChunks: {
  12. chunks: "all", // async表示抽取异步模块,all表示对所有模块生效,initial表示对同步模块生效
  13. cacheGroups: {
  14. vendors: { // 抽离第三方插件
  15. test: /[\\/]node_modules[\\/]/, // 指定是node_modules下的第三方包
  16. name: "vendors",
  17. priority: -10 // 抽取优先级
  18. },
  19. utilCommon: { // 抽离自定义工具库
  20. name: "common",
  21. minSize: 0, // 将引用模块分离成新代码文件的最小体积
  22. minChunks: 2, // 表示将引用模块如不同文件引用了多少次,才能分离生成新chunk
  23. priority: -20
  24. }
  25. }
  26. },
  27. // 为 webpack 运行时代码创建单独的chunk
  28. runtimeChunk:{
  29. name:'manifest'
  30. }
  31. }

提前公共文件之后,bundle文件变小了
image.png

十一、配置别名

  1. reolsve: {
  2. alias: { // 别名
  3. "@": './src'
  4. },
  5. // 命中率高的往前写,命中率低的往后写
  6. extensions: ['', '.js', '.json'] // 配置扩展名(引入模块的时候,可以不加扩展名)
  7. }

配置别名可以缩短查找时间,也就可以优化打包时间。

十二、优化方案

1、缩小文件搜索范围

  1. // 当你引入一个模块的时候,要进行解析
  2. resolve: {
  3. // 当你需要指定node_modules之外的其他模块目录的话
  4. modules: [path.resolve(__dirname, 'node_modules')],
  5. alias: {
  6. // 当加载react模块的时候,
  7. react: path.resolve('./cjs/react.production.min.js')
  8. }
  9. }

2、noParse 不处理的模块

module.noParse配置可以让webpack忽略对部分没采用慕课话的文件的递归解析处理

  1. module: {
  2. noParse: [/react\.min\.js/]
  3. }
  4. 被忽略掉的文件里不应该包含import require define等模块化语句
  1. // 如果打包的文件过大
  2. rules: [
  3. {
  4. test: /\.jsx?$/,
  5. use: [
  6. {
  7. loader: 'babel-loader'
  8. }
  9. ],
  10. // 只转换或者编译src目录下的文件
  11. include: path.resolve('./src'),
  12. // 排除node_modules
  13. exclude: /node_modules/
  14. }
  15. ]

noParse减少打包查询时间,也可以减少打包文件的大小。从而提高构建性能。

3、DLL

.dll为后缀的文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据。

  • 把基础模块独立处理打包到单独的动态链接库里
  • 当需要导入的模块在动态链接库里的时候,模块不能再次被打包,而是去动态链接库里获取dll-plugin

1、定义DLL

  • DllPlugin插件:用于打包一个个动态链接库
  • DllReferencePlugin:在配置文件中引入DllPlugin插件打包好的动态链接库

    4、优化loader的配置

    通过include去命中 只有哪些文件去处理,通过exclude去除哪些文件不需要处理,例如node_module

    5、优化resolve.modules配置

    1. resolve.modules用于配置Webpack去哪些目录下寻找第三方模块。
    2. resolve.modelus的默认值是['node_modules']含义是先去当前目录的./node_modules目录下去找我们想找的模块,如果没找到,就去上一级目录../node_modules中找,再没有就去../../node_modules中找,以此类推
    3. 当安装的第三方模块都放在项目根目录的./node_modules目录下时,就没有必要按照默认的方式去一层层的寻找,可以指明存放第三方模块的绝对路径,以减少寻找,配置如下:
    4. module.exports = {
    5. resolve: {
    6. // 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
    7. // 其中,__dirname表示当前工作目录,也就是项目根目录
    8. modules: [path.resolve(__dirname,'node_modules')]
    9. }
    10. }

    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只能执行脚本命令

    十五、监控源文件的变化

    1. // 表示监控源文件的变化,当源文件发售改变后,则重新打包
    2. watch: true,
    3. watchOptions: {
    4. exclude/ignored: /node_modules/,
    5. poll: 1000, // 每秒中询问的次数
    6. aggregateTimeout: 500, //
    7. }

    十六、文件拷贝

    一些不需要打包的依赖文件,需要同时拷贝过去 ```javascript copy-webpack-plugin

const CopyWebpackPlugin = require(‘copy-webpack-plugin’) plugins: [ new CopyWebpackPlugin([{ form: path.join(dirname, ‘public’), to: path.join(dirname, ‘dist’) }]) ]

  1. <a name="aSAzy"></a>
  2. ## 十七、自动更新
  3. <a name="H2zNI"></a>
  4. ## 十八、区分环境
  5. <a name="3tXUo"></a>
  6. ## 十九、配置CDN
  7. <a name="ZvOdB"></a>
  8. ## 二十、Tree-shaking
  9. 前端中的tree-shaking可以理解为通过工具"摇"我们的JS文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。具体来说,在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。<br />Tree-shaking的本质是消除无用的js代码。无用代码消除在广泛存在于传统的编程语言编译器中,编译器可以判断出某些代码根本不影响输出,然后消除这些代码,这个称之为DCE(dead code elimination)。<br />Tree-shaking 是 DCE 的一种新的实现,Javascript同传统的编程语言不同的是,javascript绝大多数情况需要通过网络进行加载,然后执行,加载的文件大小越小,整体执行时间更短,所以去除无用代码以减少文件体积,对javascript来说更有意义。
  10. <a name="xRzXh"></a>
  11. ## 二十一、开启Scope Hoisting
  12. 是webpack3推出的新功能,直译”作用域提升“,他可以让webpack打包出来的代码文件更小,运行更快。<br />webpack将引入的js文件提升大屏它的引入者的顶部
  13. ```javascript
  14. // main.js
  15. export default "hello leo~";
  16. // index.js
  17. import str from "./main.js";

开启和不开启打包的文件大小不一样。
好处:

  • 代码体积更小,因为函数声明语句中会产生大量代码,导致包的体积增大
  • 代码在运行时会因为创建的函数作用域更少,内存开销也会变小

    1、原理

    Scope Hoisting 的实现原理其实很简单:分析出模块之间的依赖关系,尽可能将打散的模块合并到一个函数中,前提是不能造成代码冗余。 因此只有那些被引用了一次的模块才能被合并

    2、使用

    1、webpack在mode为production时,会默认启用Scope Hoisting
    2、手动
    配置ModuleConcatenationPlugin插件
    1. new webpack.optimize.ModuleConcatenationPlugin();

    二十二、代码分离

    二十三、懒加载