• 认真过一遍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

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

    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 引入

    1. npm webpack webpack-cli -g
    2. npm webpack webpack-cli -D

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

    新建 index.js 入口文件

    1. function add(x, y) {
    2. return x+y;
    3. }
    4. 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 文件

    初始配置模板:

    1. /**
    2. * webpack.config.js webpack的配置文件
    3. *
    4. * 作用: 指示webpack 干哪些活( 当运行 webpack 指令时,会加载里面的配置)
    5. *
    6. * 所有构建工具都是基于 node.js 平台运行的 —— 模块化默认采用 common.js
    7. */
    8. // resolve 用来拼接绝对路径的方法
    9. const { resolve } = require('path');
    10. module.exports = {
    11. // 入口
    12. entry: './src/index.js',
    13. // 输出
    14. output: {
    15. // 输出文件名
    16. filename: 'built.js',
    17. // 输出路径,绝对路径
    18. // __dirname nodejs的变量,代表当前文件的目录绝对路径
    19. path: resolve(__dirname, 'build')
    20. },
    21. // loader 的配置
    22. module: {
    23. rules: [
    24. // 详细 loader 配置
    25. // 不同文件必须配置不同loader 配置
    26. {
    27. // test 匹配哪些文件
    28. test: /\.css$/,
    29. //使用哪些 loader 进行处理
    30. use: [
    31. // use 数组中 loader 执行顺序: 从右到左,从下到上,依次执行
    32. // 创建style 标签,将 js 中的样式资源插入进去,添加到 head 中生效
    33. 'style-loader',
    34. // 将css文件变成commonjs模块加载 js 到中,里面内容是样式字符串
    35. 'css-loader'
    36. ]
    37. },
    38. {
    39. test: /\.less$/,
    40. use: [
    41. 'style-loader',
    42. 'css-loader',
    43. // 将less文件编译成 css文件
    44. 'less-loader'
    45. ]
    46. }
    47. ]
    48. },
    49. // plugins 的配置
    50. plugins: [
    51. // 详细 plugins 的配置
    52. ],
    53. // 模式
    54. mode: 'development', // 或 'production'
    55. }

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

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

    4. 打包 html资源

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

    plugins 引入 html-webpack-plugins

    1. const { resolve } = require('path')
    2. const HtmlWebpackPlugin = require('html-webpack-plugin');
    3. module.exports = {
    4. entry: './src/index.js',
    5. output: {
    6. filename: 'built.js',
    7. path: resolve(__dirname, 'build')
    8. },
    9. module: {
    10. rules: []
    11. },
    12. plugins: [
    13. // html-webpack-plugin
    14. // 功能: 默认会创建一个空的 html,自动引入打包输出的所有资源(JS/CSS)
    15. // 需要有结构的html文件
    16. new HtmlWebpackPlugin({
    17. // 复制 ./src/index.html 文件, 并自动引入打包输出的所有资源(JS/CSS)
    18. template: './src/index.html'
    19. })
    20. ],
    21. mode: 'development'
    22. }

    5.  打包图片资源

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

     在index.less 文件中 引入 图片

    1. body,html {
    2. margin: 0;
    3. padding:0;
    4. }
    5. .one {
    6. height: 100px;
    7. width: 200px;
    8. background-image: url('./1.jpg');
    9. background-repeat: no-repeat;
    10. background-size: 100% 100%;
    11. }
    12. .tow {
    13. height: 200px;
    14. width: 200px;
    15. background-image: url('./2.png');
    16. background-repeat: no-repeat;
    17. background-size: 100% 100%;
    18. }
    19. .three {
    20. height: 300px;
    21. width: 300px;
    22. background-image: url('./3.jpg');
    23. background-repeat: no-repeat;
    24. background-size: 100% 100%;
    25. }

    index.html 文件

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>打包图片资源title>
    8. head>
    9. <body>
    10. <div id="app">
    11. <div class="one">div>
    12. <div class="tow">div>
    13. <div class="three">div>
    14. <img src="./1.jpg" alt="图片">
    15. div>
    16. body>
    17. html>

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

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

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

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

    6. 打包其他资源

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

    以 引入 iconfont 字体库 为例

    webpack5:

    1. module.exports = {
    2. ........
    3. ..........
    4. ............
    5. {
    6. // 处理图片资源 webpack5图片新打包方法
    7. test: /\.(jpg|png|gif)$/,
    8. // webpack5中使用assets-module(url-loader已废弃)
    9. type: 'asset/resource',
    10. parser: {
    11. dataUrlCondition: {
    12. maxSize: 10 * 1024
    13. }
    14. },
    15. generator: {
    16. filename: 'img/[name].[hash:6][ext]',
    17. publicPath: './'
    18. }
    19. },
    20. ...
    21. ...
    22. }

    index.js 引入 iconfont.css

    webpack.config.js

    1. const HtmlWebpackPlugin = require("html-webpack-plugin")
    2. const { resolve } = require('path')
    3. module.exports = {
    4. entry: './src/index.js',
    5. output: {
    6. filename: 'built.js',
    7. path: resolve(__dirname, 'build'),
    8. },
    9. module: {
    10. rules:[
    11. {
    12. test: /\.css$/,
    13. use: ['style-loader', 'css-loader']
    14. }
    15. ]
    16. },
    17. plugins: [
    18. new HtmlWebpackPlugin({
    19. template: './src/index.html'
    20. })
    21. ],
    22. mode: 'development'
    23. }

    webpack4: 需要加上 url-loader

    1. // 打包其他资源( 除了 html/css/js 资源以外的资源
    2. {
    3. // 排除css/js/html资源
    4. exclude: /\.(css|js|html)$/,
    5. loader: 'url-loader',
    6. options: {
    7. type: 'javascript/auto',
    8. esModule: false,
    9. }
    10. }

    7. devserve 热更新

    下载  webpack-dev-server

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

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

    // 启动 devServer 指令:

            webpack4:  npx webpack-dev-server

            webpack5: npx webpack server

    1. const HtmlWebpackPlugin = require("html-webpack-plugin")
    2. const { resolve } = require('path')
    3. module.exports = {
    4. entry: './src/index.js',
    5. output: {
    6. filename: 'built.js',
    7. path: resolve(__dirname, 'build'),
    8. },
    9. module: {
    10. rules:[
    11. {
    12. test: /\.css$/,
    13. use: ['style-loader', 'css-loader']
    14. },
    15. ]
    16. },
    17. plugins: [
    18. new HtmlWebpackPlugin({
    19. template: './src/index.html'
    20. })
    21. ],
    22. mode: 'development',
    23. // 开发服务器 devServer: 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~)
    24. // 特点: 只会在内存中编译打包,不会有任何输出
    25. // 启动 devServer 指令为: npx webpack-dev-server
    26. devServer: {
    27. static: {
    28. directory: resolve(__dirname, 'public')
    29. },
    30. // 启动gzip压缩
    31. compress: true,
    32. port: 9000,
    33. // 启动后打开默认浏览器
    34. open: true
    35. }
    36. }

    8. 提取 css 成单独文件

    下载 mini-css-extract-plugin

    配置loader 和 plugin

    loader:

    1. module: {
    2. rules: [
    3. {
    4. test: /\.css$/,
    5. MiniCssExtractPlugin.loader,
    6. 'css-loader',
    7. ]
    8. }

    plugin:

    1. plugins: [
    2. new MiniCssExtractPlugin({
    3. filename: 'css/built.css',
    4. })
    5. ]

    结果:

    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 

    1. {
    2. test: /\.css$/,
    3. use: [
    4. // 创建style标签,插入
    5. // 'style-loader',
    6. // 取代 style-loader, 提取js中的 css成单独文件
    7. MiniCssExtractPlugin.loader,
    8. // 将css文件 整合到js文件中
    9. 'css-loader',
    10. // 使用默认配置
    11. // 'postcss-loader'
    12. // 需修改 postcss loader 配置
    13. {
    14. loader: 'postcss-loader',
    15. options: {
    16. postcssOptions: {
    17. plugins: [
    18. ['postcss-preset-env',{}]
    19. ]
    20. }
    21. }
    22. }
    23. ]
    24. },

    package.json 加上browserslist 配置

    1. "browserslist": {
    2. "development": [
    3. "last 1 chrome version",
    4. "last 1 firefox version",
    5. "last 1 safari version"
    6. ],
    7. "production": [
    8. ">0.2%",
    9. "not dead",
    10. "not op_mini all"
    11. ]
    12. }

    10. css 压缩

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

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

    添加配置

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

    webpack.config.js

    1. const { resolve } = require("path");
    2. const HtmlWebpackPlugin = require('html-webpack-plugin')
    3. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    4. const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
    5. // 设置 nodejs 环境变量
    6. process.env.NODE_ENV = 'development';
    7. module.exports = {
    8. entry: './src/index.js',
    9. output: {
    10. filename: 'js/built.js',
    11. path: resolve(__dirname, 'build')
    12. },
    13. module: {
    14. rules: [
    15. {
    16. test: /\.css$/,
    17. use: [
    18. // 取代 style-loader, 提取js中的 css成单独文件
    19. MiniCssExtractPlugin.loader,
    20. // 将css文件 整合到js文件中
    21. 'css-loader',
    22. // 需修改 postcss loader 配置
    23. {
    24. loader: 'postcss-loader',
    25. options: {
    26. postcssOptions: {
    27. plugins: [
    28. ['postcss-preset-env',{}]
    29. ]
    30. }
    31. }
    32. }
    33. ]
    34. },
    35. {
    36. test: /\.html$/,
    37. loader: 'html-loader'
    38. }
    39. ]
    40. },
    41. optimization: {
    42. minimizer: [
    43. // 在 webpack@5 中,你可以使用 `...`
    44. // 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
    45. new CssMinimizerPlugin(),
    46. ],
    47. minimize:true,
    48. },
    49. plugins: [
    50. new HtmlWebpackPlugin({
    51. template: './src/index.html'
    52. }),
    53. new MiniCssExtractPlugin({
    54. filename: 'css/built.css', // 输出的内容重命名
    55. }),
    56. ],
    57. mode: 'development',
    58. devServer: {
    59. static: {
    60. directory: resolve(__dirname, 'public')
    61. },
    62. // 启动 gzip压缩
    63. compress: true,
    64. port: 3000,
    65. open: true,
    66. }
    67. }

    11. js语法检查

    webpack5 插件: eslint-webpack-plugin

    webpack4 : eslint-loader (webpack5 已弃用)

    webpack5

    1. const ESLintWebpackPlugin = require('eslint-webpack-plugin');
    2. ............
    3. ...............
    4. ....................................
    5. plugins: [
    6. new ESLintWebpackPlugin({
    7. fix: true,
    8. }),
    9. ],

    package.json 还需要加上 eslint 配置 

    1. "eslintConfig": {
    2. "env": {
    3. "browser": true
    4. }
    5. },

    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兼容性问题

    1. module: {
    2. rules: [
    3. {
    4. test: /\.js$/,
    5. exclude: /node_modules/,
    6. loader: 'babel-loader',
    7. options: {
    8. // 预设: 指示babel 做什么样的兼容性处理, 智能按需引入polyfill
    9. presets: [['@babel/preset-env',{
    10. // 按需加载
    11. useBuiltIns: 'usage',
    12. // 指定 core-js版本
    13. corejs: {
    14. version: 3
    15. },
    16. // 指定兼容哪个版本浏览器
    17. targets: {
    18. chrome: '60',
    19. firefox: '60',
    20. ie: '9',
    21. safari: '10',
    22. edge: '17'
    23. }
    24. }]]
    25. },
    26. }
    27. ]
    28. }

    13. js、html 压缩

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

      mode: 'production',

    html 压缩,直接配置 HtmlWebpackPlugin

    1. plugins: [
    2. new HtmlWebpackPlugin({
    3. template: './src/index.html',
    4. // 压缩 html代码
    5. minify: {
    6. // 移除空格
    7. collapseWhitespace: true,
    8. // 移除空格
    9. removeComments: true
    10. }
    11. })
    12. ]

    14 生产环境基本配置

    webpack.config.js

    1. const { resolve } = require('path')
    2. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    3. const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
    4. const HtmlWebpackPlugin = require('html-webpack-plugin')
    5. process.env.NODE_ENV = 'production'
    6. const commonCssLoader = [
    7. MiniCssExtractPlugin.loader,
    8. 'css-loader',
    9. {
    10. loader: 'postcss-loader',
    11. options: {
    12. postcssOptions: {
    13. plugins:[
    14. [
    15. 'postcss-preset-env',
    16. {
    17. }
    18. ]
    19. ]
    20. }
    21. }
    22. }
    23. ]
    24. module.exports = {
    25. entry: './src/index.js',
    26. output: {
    27. filename: 'js/built.js',
    28. path: resolve(__dirname, 'build')
    29. },
    30. module: {
    31. rules: [
    32. {
    33. test: /\.css$/,
    34. use: [...commonCssLoader]
    35. },
    36. {
    37. test: /\.less$/,
    38. use: [...commonCssLoader, 'less-loader']
    39. },
    40. {
    41. test: /\.js$/,
    42. exclude: /node_modules/,
    43. loader: 'babel-loader',
    44. options: {
    45. presets: [
    46. [
    47. '@babel/preset-env',
    48. {
    49. useBuiltIns: 'usage',
    50. corejs: { version: 3},
    51. targets: {
    52. chrome: '60',
    53. firefox: '60',
    54. ie: '9',
    55. safari: '10',
    56. edge: '17'
    57. }
    58. }
    59. ]
    60. ]
    61. }
    62. },
    63. {
    64. // 处理图片资源 webpack5图片新打包方法
    65. test: /\.(jpg|png|gif)$/,
    66. // webpack5中使用assets-module(url-loader已废弃)
    67. type: 'asset/resource',
    68. parser: {
    69. dataUrlCondition: {
    70. maxSize: 10 * 1024
    71. }
    72. },
    73. generator: {
    74. filename: 'img/[name].[hash:6][ext]',
    75. publicPath: './'
    76. }
    77. },
    78. {
    79. test: /\.(eot|ttf|otf|woff2?)$/,
    80. type: 'asset',
    81. generator: {
    82. filename: 'fonts/[name].[hash:8][ext]'
    83. }
    84. },
    85. {
    86. test: /\.html/,
    87. loader: 'html-loader'
    88. },
    89. {
    90. exclude: /\.(js|css|less|html|jpg|png|gif|eot|ttf|otf|woff2)$/,
    91. loader: 'file-loader',
    92. options: {
    93. outputPath: 'media'
    94. }
    95. }
    96. ]
    97. },
    98. optimization: {
    99. minimizer: [
    100. new CssMinimizerWebpackPlugin()
    101. ],
    102. minimize: true,
    103. },
    104. plugins: [
    105. new HtmlWebpackPlugin({
    106. template: './src/index.html',
    107. minify: {
    108. collapseWhitespace: true,
    109. removeComments: true,
    110. }
    111. }),
    112. // 提取css成单独文件
    113. new MiniCssExtractPlugin({
    114. filename: 'css/built.css'
    115. }),
    116. ],
    117. mode: 'production',
    118. devServer: {
    119. static: {
    120. directory: resolve(__dirname, 'public')
    121. },
    122. compress: true,
    123. port: 3000,
    124. open: true,
    125. // 当修改了 webpack配置,想要 新配置生效,必须要重新打包
    126. hot: true,
    127. }
    128. }

    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

    1. devServer: {
    2. static: {
    3. directory: resolve(__dirname, 'public')
    4. },
    5. compress: true,
    6. port: 3000,
    7. open: true,
    8. // 当修改了 webpack配置,想要 新配置生效,必须要重新打包
    9. hot: true,
    10. }

    样式文件:可以使用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

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

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

            速度快(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上面即可,

    1. module: {
    2. rules: [
    3. {
    4. test: /\.js$/,
    5. exclude: /node_modules/,
    6. exforce: 'pre',
    7. loader: 'eslint-loader',
    8. options: {
    9. fix: true
    10. }
    11. },
    12. {
    13. oneOf: [
    14. {
    15. test: /\.js$/,
    16. exclude: /node_modules/,
    17. loader: 'babel-loader',
    18. options: {
    19. presets: [
    20. [
    21. '@babel/preset-env',
    22. {
    23. useBuiltIns: 'usage',
    24. corejs: { version: 3},
    25. targets: {
    26. chrome: '60',
    27. firefox: '60',
    28. ie: '9',
    29. safari: '10',
    30. edge: '17'
    31. }
    32. }
    33. ]
    34. ]
    35. }
    36. },
    37. ]
    38. }
    39. ],
    40. },

    19. 缓存

    1. babel 缓存

            cacheDirectory: true

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

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

    1. {
    2. test: /\.js$/,
    3. exclude: /node_modules/,
    4. loader: 'babel-loader',
    5. options: {
    6. presets: [
    7. [
    8. '@babel/preset-env',
    9. {
    10. useBuiltIns: 'usage',
    11. corejs: { version: 3},
    12. targets: {
    13. chrome: '60',
    14. firefox: '60',
    15. ie: '9',
    16. safari: '10',
    17. edge: '17'
    18. }
    19. }
    20. ]
    21. ],
    22. // 开启babel缓存
    23. // 第二次构建时,会读取之前的缓存
    24. cacheDirectory: true
    25. }
    26. },

    2. 文件资源缓存

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

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

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

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

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

    输出js文件:取 contenthash 值 10位

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

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

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

    20. tree shaking

    去掉没有用代码

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

            作用: 减少代码体积

            在package.json 中配置

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

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

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

     21. 代码分隔 code split

    1. 多入口文件

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

    1. // 多入口
    2. entry: {
    3. main: './src/index.js',
    4. test: './src/test.js'
    5. },

    2.  module.exports中 配置 optimization

    /**

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

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

       */

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

    3. 通过js 代码单独打包

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

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

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

    22. 懒加载 lazy loading

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

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

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

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

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

    渐进式网络应用程序 PWA

    官网上截取:

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

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

     webpack.config.js

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

    注册 Service Worker

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

    index.js

    1. + if ('serviceWorker' in navigator) {
    2. + window.addEventListener('load', () => {
    3. + navigator.serviceWorker.register('/service-worker.js').then(registration => {
    4. + console.log('SW registered: ', registration);
    5. + }).catch(registrationError => {
    6. + console.log('SW registration failed: ', registrationError);
    7. + });
    8. + });
    9. + }

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

    1. "eslintConfig": {
    2. "env": {
    3. "browser": true
    4. }
    5. },

    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

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

    webpack.config.js

    1. module.exports = {
    2. //...
    3. externals: {
    4. jquery: 'jQuery',
    5. },
    6. };

    26 DllPlugin

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

  • 相关阅读:
    【面试题】——JavaIO篇(23题)
    Linux服务器搭建Docker
    注册Java 引用类型 (class、interface) 用法总结详解
    设计模式—结构型模式之享元模式
    Android12之强弱智能指针sp/wp循环引用死锁问题(一百六十六)
    服务器的数据库连不上了2003,10060“Unknown error“【服务已起、防火墙已关、端口已开、netlent 端口不通】
    java使用正则提取数据
    MongoDB学习笔记
    【React 】useLayoutEffect 和 useEffect的区别
    简单神经网络算法原理,人工神经网络算法原理
  • 原文地址:https://blog.csdn.net/weixin_41184962/article/details/126387731