webpack学习

目录

 

1. 简介

1.  Entry 入口

2. Output 

3. Loader

4. Plugins

5. Model

2. webpack 体验

1. 开发环境控制台 输入 指令:

 2. 生产环境控制台 输入 指令:

 3.node 运行这个文件,输出 3

结论:

3. webpack 打包样式资源

4. 打包 html资源

5.  打包图片资源

6. 打包其他资源

webpack5:

webpack4: 需要加上 url-loader

7. devserve 热更新

8. 提取 css 成单独文件

9. css兼容性处理

10. css 压缩

11. js语法检查

12. js 兼容性处理

13. js、html 压缩

14 生产环境基本配置

15. 性能优化

webpack优化

开发环境性能优化

生产环境性能优化

16. HMR

17. source-map

18. oneOf

19. 缓存

1. babel 缓存

2. 文件资源缓存

20. tree shaking

 21. 代码分隔 code split

22. 懒加载 lazy loading

23. PWA渐进式网络应用程序

注册 Service Worker

24. 多进程打包

25. externals 外部扩展

externals

26 DllPlugin


1. 简介

Webpack 是 前端资源打包工具,它会根据模块之间的依赖关系进行静态分析,将模块按照指定的规则生成对应的静态资源。 

 webpack会从入口文件开始打包,先形成依赖关系图,根据依赖图把不同的资源引进来形成一个chunk代码块, 然后根据chunk根据不同的资源进行处理,比如: less => css, 这个处理过程就是 打包,打包之后输出去,输出去的文件 就是 bundle。

 Webpack 处理是会构建出一个依赖图,该依赖图映射项目所需的每个模块,并将多种静态资源 js、css、less 转换成一个静态文件bundle.js,减少了页面的请求。

从 v4.0.0 开始,webpack 可以不用再引入一个配置文件来打包项目,然而,但它仍然有着 高度可配置性

1.  Entry 入口

入口指示Webpack 以哪个文件为起点开始打包,分析构建内部 依赖图(dependency graph) 。默认是 './src/index.js', 可以通过配置指定 entry 属性,指定一个或多个 入口起点。

webpack.config.js

module.exports = {
    entry: './src/index.js'
}

2. Output 

输出指示Webpack打包后的资源bundle 输出到哪里去,以及如何命名。

3. Loader

Loader 让 Webpack 能够去处理那些非 JavaScript 文件(Webpack 自身只理解JavaScript),把文件转成 webpack可以识别的 js 文件。

4. Plugins

插件(plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。

5. Model

通过选择 developmentproduction 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production

2. webpack 体验

1. 新建文件夹, npm init

2. 引入 webpack webpack-cli,  先 -g 全局引入(这样可以直接用 webpack-cli 的命令),再 -D 引入

npm webpack webpack-cli -g

npm webpack webpack-cli -D

3. 新建代码文件夹 src, 打包输出的文件夹 build

新建 index.js 入口文件


function add(x, y) {
  return x+y;
}
console.log(add(1,2));

/**
 * index,js: webpack 入口起点文件
 * 1. 运行指令
 *    开发环境: webpack ./src/index.js -o ./build/built.js --mode=development
 *    webpack会以  ./src/index.js 为入口文件开始打包,打包输出到  ./build/built/main.js
 *    整体打包环境,是开发环境
 * 
 *    生产环境:webpack ./src/index.js -o ./build/built.js --mode=production
 *    webpack会以  ./src/index.js 为入口文件开始打包,打包输出到  ./build/built/main.js
 *    整体打包环境,是生产环境
 */

1. 开发环境控制台 输入 指令:

webpack ./src/index.js -o ./build/built.js --mode=development

会生成built.js/main.js, main.js里面是 打包的内容 

main.js 文件 eval 函数 包含了 index.js 的所有内容,包括注释。 

 2. 生产环境控制台 输入 指令:

webpack ./src/index.js -o ./build/built.js --mode=production

 文件 main.js 里面 是 webpack帮你压缩好的 代码了,我的是 webpack5, 好家伙,直接剩下一个运行语句

 3.node 运行这个文件,输出 3

node .\build\built.js\main.js

结论:

1. webpack 能处理 js/json文件,不能处理css/img等其他资源

2. 生产环境和开发环境将 ES6 模块化编译成浏览器能识别的模块化

3. 生产环境比开发环境多一个压缩 js 代码。

3. webpack 打包样式资源

src 文件夹 下建 index.js(入口文件), index.css 样式文件, index.less 样式

build 文件夹,建  index.html

根目录新建一个 webpack.config.js 文件

初始配置模板:

/**
 * webpack.config.js webpack的配置文件
 * 
 *    作用: 指示webpack 干哪些活( 当运行 webpack 指令时,会加载里面的配置)
 * 
 *    所有构建工具都是基于 node.js 平台运行的 —— 模块化默认采用 common.js
 */
// resolve 用来拼接绝对路径的方法
const { resolve } = require('path');
module.exports = {
  // 入口
  entry: './src/index.js',
  // 输出
  output: {
    // 输出文件名
    filename: 'built.js',
    // 输出路径,绝对路径
    // __dirname nodejs的变量,代表当前文件的目录绝对路径
    path: resolve(__dirname, 'build')
  },
  // loader 的配置
  module: {
    rules: [
      // 详细 loader 配置
      // 不同文件必须配置不同loader 配置
      {
        // test 匹配哪些文件
        test: /\.css$/,
        //使用哪些 loader 进行处理
        use: [
          // use 数组中 loader 执行顺序: 从右到左,从下到上,依次执行
          // 创建style 标签,将 js 中的样式资源插入进去,添加到 head 中生效
          'style-loader',
          // 将css文件变成commonjs模块加载 js 到中,里面内容是样式字符串
          'css-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          // 将less文件编译成 css文件
          'less-loader'
        ]
      }
    ]
  },
  // plugins 的配置
  plugins: [
    // 详细 plugins 的配置
  ],
  // 模式
  mode: 'development', // 或 'production'
}

注意:__dirname 是两个 _ , 写少一个 bug找半天

控制台输入 webpack 即可 运行打包,并且 index.css的样式 生效于 index.html中

4. 打包 html资源

/**
 * loader : 1.下载 2. 使用(配置loader)
 * plugins:  1. 下载 2. 引入  3. 使用
 */

plugins 引入 html-webpack-plugins


const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: []
  },
  plugins: [
    // html-webpack-plugin
    // 功能: 默认会创建一个空的 html,自动引入打包输出的所有资源(JS/CSS)
    // 需要有结构的html文件
    new HtmlWebpackPlugin({
      // 复制 ./src/index.html 文件, 并自动引入打包输出的所有资源(JS/CSS)
      template: './src/index.html'
    })
  ],
  mode: 'development'
} 

5.  打包图片资源

webpack5 自带图片处理,可以直接使用 assets Module, webpack4 的话 就要 加上 url-loader, 有的还需要 加 file-loader.

 在index.less 文件中 引入 图片

body,html {
  margin: 0;
  padding:0;
}

.one {
  height: 100px;
  width: 200px;
  background-image: url('./1.jpg');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
.tow {
  height: 200px;
  width: 200px;
  background-image: url('./2.png');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
.three {
  height: 300px;
  width: 300px;
  background-image: url('./3.jpg');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

index.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>打包图片资源</title>
</head>
<body>
  <div id="app">
    <div class="one"></div>
    <div class="tow"></div>
    <div class="three"></div>
    <img src="./1.jpg" alt="图片">
  </div>
</body>
</html>

url-loader: webpack5的 不用 加该loader, webpack5会自动处理.


      {
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,           
        // 下载url-loader file-loader
        loader: 'url-loader',
        options: {
          // 图片大小小于 300kb, 就会被 base64处理
          // 优点:减少请求数量(减轻服务器压力)
          // 优点:  图片体积会更大(文件请求速度更慢)
          limit: 200 * 1024,
          // 问题: 因为url-loader默认使用 es6 模块化解析,而 html-loader 引入图片是 commonjs
          // 解析时会出现问题: [object Module]
          // 解决: 关闭 url-loader 的 es6 模块化, 使用 commonjs 解析
          esModule: false,
          // 给图片进行重命名(没必要)
          // [hash:10] 取图片的hash 的前 10位
          // [ext] 取文件原来扩展名
          // name: '[hash:10].[ext]'
        }
      }

 html-loader: 处理html文件的img 图片(负责引入img,从而被 url-loader 进行处理)


      {
        test: /\.html$/,
        // 处理html文件的img 图片(负责引入img,从而被 url-loader 进行处理)
        loader: 'html-loader'
      }

6. 打包其他资源

同样 webpack 5 会自动处理或用 asset Module 处理,不需要另外加 url-loader

以 引入 iconfont 字体库 为例

webpack5:

module.exports = {
........
..........
............
{
        // 处理图片资源  webpack5图片新打包方法
        test: /\.(jpg|png|gif)$/,
        // webpack5中使用assets-module(url-loader已废弃)
        type: 'asset/resource',
        parser: {
            dataUrlCondition: {
              maxSize: 10 * 1024
            }
        },
        generator: {
            filename: 'img/[name].[hash:6][ext]',
            publicPath: './'
        }
      },
...
...
}

index.js 引入 iconfont.css

webpack.config.js

const HtmlWebpackPlugin = require("html-webpack-plugin")
const { resolve } = require('path')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path:  resolve(__dirname, 'build'),
  },
  module: {
    rules:[
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development'
}

webpack4: 需要加上 url-loader

 // 打包其他资源( 除了 html/css/js 资源以外的资源
      {
        // 排除css/js/html资源
        exclude: /\.(css|js|html)$/,
        loader: 'url-loader',
        options: {
          type: 'javascript/auto',
          esModule: false,
        }
      }

7. devserve 热更新

下载  webpack-dev-server

// 开发服务器 devServer: 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~)

// 特点: 只会在内存中编译打包,不会有任何输出

// 启动 devServer 指令:

        webpack4:  npx webpack-dev-server

        webpack5: npx webpack server

const HtmlWebpackPlugin = require("html-webpack-plugin")
const { resolve } = require('path')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path:  resolve(__dirname, 'build'),
  },
  module: {
    rules:[
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',

  // 开发服务器 devServer: 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~)
  // 特点: 只会在内存中编译打包,不会有任何输出
  // 启动 devServer 指令为: npx webpack-dev-server
  devServer: {
    static: {
      directory: resolve(__dirname, 'public')
    },
    // 启动gzip压缩
    compress: true,
    port: 9000,
    // 启动后打开默认浏览器
    open: true
  }
}

8. 提取 css 成单独文件

下载 mini-css-extract-plugin

配置loader 和 plugin

loader:

module: {

    rules: [
        {
            test: /\.css$/,
            MiniCssExtractPlugin.loader,
            'css-loader',
    ]
}

plugin:

plugins: [
    new MiniCssExtractPlugin({
        filename: 'css/built.css',
    })
]

结果:

9. css兼容性处理

/**   postcss-loader

  * css 兼容性处理: postcss ---> postcss-loader postcss-preset-env

   *  帮助 postcss 找到 package.json 中 browserslist 里面的配置,通过配置加载指定的css兼容性样式

 */

1. 设置 nodejs 环境变量

webpack.config.js 加上

process.env.NODE_ENV = 'development';

loader 中配置:webpack5 

{
        test: /\.css$/,
        use: [
          // 创建style标签,插入
          // 'style-loader', 
          // 取代 style-loader, 提取js中的 css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件 整合到js文件中
          'css-loader',
          // 使用默认配置
          // 'postcss-loader'
          // 需修改 postcss loader 配置
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  ['postcss-preset-env',{}]
                ]
              }
            }
          }
        ]
      },

package.json 加上browserslist 配置


  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }

10. css 压缩

webpack4 用插件: optimize-css-assets-webpack-plugin

webpack5 用插件:css-minimizer-webpack-plugin

添加配置

 optimization: {
    minimizer: [
      // 在 webpack@5 中,你可以使用 `...` 
      // 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
      // `...`,
      new CssMinimizerPlugin(),
    ],
    minimize:true, 
  },

webpack.config.js

const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin  = require('css-minimizer-webpack-plugin')
// 设置 nodejs 环境变量
process.env.NODE_ENV = 'development';

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 取代 style-loader, 提取js中的 css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件 整合到js文件中
          'css-loader',
          // 需修改 postcss loader 配置
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  ['postcss-preset-env',{}]
                ]
              }
            }
          }
        ]
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      }
    ]
  },
  optimization: {
    minimizer: [
      // 在 webpack@5 中,你可以使用 `...` 
      // 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
      new CssMinimizerPlugin(),
    ],
    minimize:true, 
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      filename: 'css/built.css', // 输出的内容重命名
    }),
  ],
  mode: 'development',
  devServer: {
    static: {
      directory: resolve(__dirname, 'public')
    },
    // 启动 gzip压缩
    compress: true,
    port: 3000,
    open: true,
  }
}

11. js语法检查

webpack5 插件: eslint-webpack-plugin

webpack4 : eslint-loader (webpack5 已弃用)

webpack5


const ESLintWebpackPlugin = require('eslint-webpack-plugin');
............
...............
....................................
plugins: [
    new ESLintWebpackPlugin({
      fix: true,
    }),
  ],

package.json 还需要加上 eslint 配置 

"eslintConfig": {
    "env": {
      "browser": true
    }
  },

12. js 兼容性处理

如果代码没有做兼容性处理, 代码 根本无法在 IE浏览器正常运行,IE 不认识 ES6 、以及ES6以上的语法; 

/**

       * js兼容性处理: babel-loader @babel/core @babel/preset-env

       *  1. 基本js 兼容处理 => @babel/preset-env

       *    问题: 只能转换基本语法, 如 promise 高级语法不能转换

       *  2. 全部js 兼容性处理  => @babel/polyfill, 直接在文件中 引入 即可使用

       *    问题: 只要解决部分兼容性问题,不需要全部兼容性的代码全部引入,体积太大

       *  3. 需要做兼容性处理: 按需引入 => core.js

       */

结合: babel-loader @babel/core 和 core.js 即可 解决 js兼容性问题

 module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 预设: 指示babel 做什么样的兼容性处理, 智能按需引入polyfill
          presets: [['@babel/preset-env',{
            // 按需加载
            useBuiltIns: 'usage',
            // 指定 core-js版本
            corejs: {
              version: 3
            },
            // 指定兼容哪个版本浏览器
            targets: {
              chrome: '60',
              firefox: '60',
              ie: '9',
              safari: '10',
              edge: '17'
            }
          }]]
        },
      }
    ]
}

13. js、html 压缩

 // 生产环境下会自动压缩代码

  mode: 'production',

html 压缩,直接配置 HtmlWebpackPlugin

plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // 压缩 html代码
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除空格
        removeComments: true
      }
    })
]

14 生产环境基本配置

webpack.config.js


const { resolve } = require('path')
const  MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

process.env.NODE_ENV = 'production'
const commonCssLoader = [
  MiniCssExtractPlugin.loader, 
  'css-loader',
  {
    loader: 'postcss-loader',
    options: {
      postcssOptions: {
        plugins:[
         [ 
            'postcss-preset-env',
            {

            }
          ]
        ]
      }
    }
  }
]
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [...commonCssLoader]
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, 'less-loader']
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                useBuiltIns: 'usage',
                corejs: { version: 3},
                targets: {
                  chrome: '60',
                  firefox: '60',
                  ie: '9',
                  safari: '10',
                  edge: '17'
                }
              }
            ]
          ]
        }
      },
      {
        // 处理图片资源  webpack5图片新打包方法
        test: /\.(jpg|png|gif)$/,
        // webpack5中使用assets-module(url-loader已废弃)
        type: 'asset/resource',
        parser: {
            dataUrlCondition: {
              maxSize: 10 * 1024
            }
        },
        generator: {
            filename: 'img/[name].[hash:6][ext]',
            publicPath: './'
        }
      },
      {
          test: /\.(eot|ttf|otf|woff2?)$/,
          type: 'asset',
          generator: {
            filename: 'fonts/[name].[hash:8][ext]'
          }
      },
      {
        test: /\.html/,
        loader: 'html-loader'
      },
      {
        exclude: /\.(js|css|less|html|jpg|png|gif|eot|ttf|otf|woff2)$/,
        loader: 'file-loader',
        options: {
          outputPath: 'media'
        }
      }
    ]
  },
  optimization: {
    minimizer: [
      new CssMinimizerWebpackPlugin()
    ],
    minimize: true,
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      }
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    }),
  ],
  mode: 'production',
  devServer: {
    static: {
      directory: resolve(__dirname, 'public')
    },
    compress: true,
    port: 3000,
    open: true,
    // 当修改了 webpack配置,想要 新配置生效,必须要重新打包
    hot: true,
  }
}

15. 性能优化

webpack优化

开发环境性能优化

优化打包构建速度

        * HMR

优化代码调试

        *source-map

生产环境性能优化

优化打包构建速度

        * oneOf
        * babel缓存

        * 多进程打包

        *extrernals

        *dll 

优化代码运行速度

        *文件资源缓存 (hash - chunkhash - contenthash)

                hash 每次打包都会成功一个 hash 值

                chunkhash 同一个chunkhash 共用一个 chunkhash 值

                contenthash 一个内容文件一个 contenthash, 内容不变,contenthash不变

        * tree shaking

        *code split

        *l懒加载/ 预加载
        *pwa    

16. HMR

HMR: hot module replacement 热模块替换 / 模块热替换

作用: 一个模块发生变化,只会重新打包这一模块(而不会打包所有模块)

        极大提高构建速度

直接在 devServer配置 加上 hot: true

 devServer: {
    static: {
      directory: resolve(__dirname, 'public')
    },
    compress: true,
    port: 3000,
    open: true,
    // 当修改了 webpack配置,想要 新配置生效,必须要重新打包
    hot: true,
  }

样式文件:可以使用HMP  功能, 因为 style-loader 内部实现了

js文件:默认不能使用HMP功能

html文件:默认不能使用 HMP功能, 同时会导致问题,html 文件不能热更新了(不需要做HMP功能)

        解决: 修改entry 入口,将html 文件引入

entry: ['./src/index.js', './src/index.html'],

17. source-map

source-map: 能提供 源代码 到 构建后代码的 映射 关系,通过映射追踪可以定位到具体代码出错的位置。

在webpack.config.js 中配置 devtool: 'source-map' 即可开启

可选值:[inline-|hidden-|eval_][nosources-][cheap-[module-]]source-map

 module.exports = {
    devtool: 'source-map',
 }

开发环境下: 速度快,调试更友好

        速度快(eval > inline > cheap....)

                eval-cheap-source-map

                eval-source-map

        调试更友好

                source-map

                cheap-module-source-map

                cheap-source-map 

生产环境:源码要不要隐藏?调试要不要友好

        内联会让代码体积变大,所以生产环境下不用内联

        nosources-source-map 全部隐藏

        hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

 --》source-map / cheap-module-source-map

18. oneOf

把loader 放到 oneOf下,oneOf 下的loader 只会匹配一个

// 注意: 不能有两个匹配处理同一种类型的文件,如有两个loader处理同一种类型文件( 如下两个loader 都处理 js 文件,把有限的一种 放在 oneOf外面),只需要把 有限处理的loader 放到 oneOf上面即可,

 module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        exforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3},
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ]
            }
          },
        ]
      }
    ],
  },

19. 缓存

1. babel 缓存

        cacheDirectory: true

        --> 让第二次打包构建速度更快

在webpack中使用babel-loader是去为了兼容我们的js代码,将更高级的语法转译成浏览器所能识别语法,但是这个过程编译过程会很慢

        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3},
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ],
              // 开启babel缓存
              // 第二次构建时,会读取之前的缓存
              cacheDirectory: true
            }
          },

2. 文件资源缓存

        hash: 每次webpack 构建时会生成一个唯一的 hash 值;

               问题: 因为js 和 css 同时使用一个 hash 值。如果重新打包,会导致所有缓存失效(可能只改一个文件)。

        chunkhash: 根据 chunk 生成的 hash 值。如果打包来源同一个 chunk,那hash值一样。

                问题: js 和 css 的hash 值还是一样的,因为 css 是在 js 中被引入的,所有属于同一个 chunk.

        contenthash: 根据文件的内容生成 hash 值。不同文件hash 值不同。 推荐使用。

输出js文件:取 contenthash 值 10位

 output: {
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },

提取的 css文件:取 contenthash 值 10位

plugins: [
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
  ],

20. tree shaking

去掉没有用代码

        前提: 1. 必须使用ES6模块化     2. 开启 production 环境

        作用: 减少代码体积

        在package.json 中配置

                "sideEffect": false 所有代码都没有副作用,都可以进行tree shaking

                        问题: 可能会把css / @babel/polyfill 文件干掉

                "sideEffects": ["*.css", "*.less"]

 21. 代码分隔 code split

1. 多入口文件

        有几个入口,就会生成 几个js文件

 // 多入口
  entry: {
    main: './src/index.js',
    test: './src/test.js'
  },

2.  module.exports中 配置 optimization

/**

   * 1. 可以将 node_modules中代码单独打包成一个 chunk 最终输出

   * 2. 自动分析多入口 chunk 中, 有没有公共的文件,如果有会打包成单独一个 chunk

   */

 optimization: {
    splitChunks: {
      chunks: 'all',
    },
    // 将当前模块记录其他模块的hash 单独打包为一个文件 runtime
    // 解决: 修改 test.js文件 导致 indexjs 文件的 contenthash 变化
    runtimeChunk: {
      name: entrypoint => `runtime-${entrypoint.name}`
    }
  },

3. 通过js 代码单独打包

        通过 js 代码,让某个文件被单独打包成一个 chunk

        import 动态导入语法: 能将某个文件单独打包

import('./test.js')
.then(({ mul, count}) => {
  // 文件加载成功
  console.log(mul(2, 5))
  console.log(count([1,2,3,4,5]))
}).catch(() => {
  // 文件加载失败
})

22. 懒加载 lazy loading

懒加载: 当文件需要使用时才加载

预加载 prefetch:会在使用前,提前加载 js 文件。(等其他资源加载完毕,浏览器空闲了,载加载资源)慎用预加载,会有兼容性问题。

点击按钮的时候,在 import 文件

document.getElementById('bnt').onclick = function () {
  import(/*webpackChunkName: 'test'*/'./test.js')
  .then(({ mul, count}) => {
    console.log(mul(2, 5))
    console.log(count([1,2,3,4,5]))
  }).catch(() => {

  })
}

23. PWA渐进式网络应用程序

渐进式网络应用程序 PWA

官网上截取:

添加 workbox-webpack-plugin 插件,然后调整 webpack.config.js 文件:

npm install workbox-webpack-plugin --save-dev

 webpack.config.js

 plugins: [
     new WorkboxPlugin.GenerateSW({
       // 这些选项帮助快速启用 ServiceWorkers
       // 不允许遗留任何“旧的” ServiceWorkers
       clientsClaim: true,
       skipWaiting: true,
     }),
    ],

注册 Service Worker

接下来我们注册 Service Worker,使其出场并开始表演。通过添加以下注册代码来完成此操作:

index.js



+ if ('serviceWorker' in navigator) {
+   window.addEventListener('load', () => {
+     navigator.serviceWorker.register('/service-worker.js').then(registration => {
+       console.log('SW registered: ', registration);
+     }).catch(registrationError => {
+       console.log('SW registration failed: ', registrationError);
+     });
+   });
+ }

 注意 package.json 如果项目加上了Eslint 检查,需要加上 支持全局变量

"eslintConfig": {
    "env": {
      "browser": true
    }
  },

24. 多进程打包

thread-loaderhttps://webpack.docschina.org/loaders/thread-loader/#root

25. externals 外部扩展

externals 排除某些文件的打包, 例如 ’jQuery'

官网截取:

externals

string object function RegExp [string, object, function, RegExp]

防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)

例如,从 CDN 引入 jQuery,而不是把它打包:

index.html

<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous"
></script>

webpack.config.js

module.exports = {
  //...
  externals: {
    jquery: 'jQuery',
  },
};

26 DllPlugin

DllPlugin 用法https://webpack.docschina.org/plugins/dll-plugin#usage

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值