webpack 5

189 阅读4分钟

开发环境

css打包

npm i css-loader style-loader -D
rules: [
 {
      test: /\.css$/,
      use: [
        // 创建style标签,将js中的样式资源插入添加到head中生效
        'style-loader',
        // 将 css 文件变成commonjs模块加载到js中,里面的内容是string类型 
        'css-loader'
        // use数组中执行顺序 从下到上,从右到左
      ]
 }
  ]

less打包

npm i less less-loader -D
rules: [
      {
        test: /\.less$/,
        use: [
          // 创建style标签,将js中的样式资源插入添加到head中生效
          'style-loader',
          // 将 css 文件变成commonjs模块加载到js中,里面的内容是string类型 
          'css-loader',
          // 把less变为css
          'less-loader'
        ]
      }
       ]

html打包

npm i html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
 plugins: [
    // 默认创建一个空的html,自动引入打包输出的所有资源(js/css)
    new HtmlWebpackPlugin(
      {
        // 复制'./src/html/index.html',自动引入打包输出的所有资源(js/css)
        template: './src/html/index.html'
      }
    )
  ],

处理图片资源

 rules: [
      // 处理图片资源(处理不了img标签的图片资源)
      {
        test: /\.(jpg|png|gif)$/,
        loader: 'url-loader',
        options: {
          // 小于8M的会成为base64(优点:减少请求数量;缺点:图片更大)
          limit: 8 * 1024,

          // 文件重命名 (img为在dist目录生成img文件,[hash:7]取七位,[ext]为原扩展名)
          name: 'img/[hash:7].[ext]',
          // 用commonJS8i
          esModule: false
        },
        // webpack5中避免资源重复
        type: 'javascript/auto'
      },
        // 处理img标签的图片资源
      {
        test: /\.html$/,
        // 处理html文件中的img图片(负责引入img,从而能被url-loader进行处理)
        loader: 'html-loader'
      }
       ]

处理其他资源(例如音频)

 rules: [
     {
        test: /\.(mp3)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          name: 'media/[name].[ext]',
          limit: 10,
          esModule: false
        },
        type: 'javascript/auto'
      }
       ]

发服务器(devServer)

  //  npm i webpack-dev-server -D
  // 开发服务器 devServer :自动编译,自动打开浏览器,自动刷新浏览器
  // 在内存中编译打包,不会有输出
  // 启动devServer的指令为webpack serve
  devServer: {
    static: { directory: resolve(__dirname, 'build') }, // 运行项目的目录:构建后的目录
    // 启动gzip压缩
    compress: true,
    port: 3000,
    open: true
  },
  // 保证更改代码保存后能够自动刷新
  target:'web'

环境

mode: 'development',
// 环境 (分为development与production)
// 生产环境会压缩js代码

生产环境

把css单独抽取成文件

若把css放在js文件中,这样让js文件体积变大,而且需要先加载js才能创建style标签插入页面中,这样会出现闪屏现象

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  rules: [
      // 打包 css
      {
        test: /\.css$/,
        use: [
          // 创建style标签,将js中的样式资源插入添加到head中生效(所以若要单独抽取成css文件,就不需要它)
          // 'style-loader',
          // 取代style-loader,把js中的css抽成css文件
          MiniCssExtractPlugin.loader,
          // 将 css 文件变成commonjs模块加载到js中,里面的内容是string类型 
          'css-loader'
          // 加载规则 从下到上,从右到左
        ]
      },
   plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/style.css'
    }),
  ],

css兼容性处理

需要用到postcss库.postcss在webpack中使用就要用到postcss-loader.

使用postcss-preset-env插件让postcss识别某些环境和加载指定的配置(比如帮webpack找到package.json中的browserslist里面的配置,通过配置加载指定的兼容性),可以让我们把兼容性做到精准到浏览器的某一个版本.

//  npm i postcss-loader postcss -D
// package.json文件
 "browserslist":{
    "development":[
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production":[
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }
// 默认是看想要browserslist生产环境,想要browserslist开发环境需要设置node环境变量
process.env.NODE_ENV='development'
module.exports = {
rules: [
      // 打包 css
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          // 将 css 文件变成commonjs模块加载到js中,里面的内容是string类型 
          'css-loader',
          // css兼容处理
               {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                  ]
                ]
              }
            }
          }
          // 加载规则 从下到上,从右到左
        ]
      }
      ]
}

压缩css

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

// 压缩css
 plugins: [
    new optimizeCssAssetsWebpackPlugin()
    ]

js兼容性处理

 npm i babel-loader @babel/core @babel/preset-env core-js -D
rules: [
  {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
        options: {
          // 预设 babel做哪些兼容性处理
          presets: [
            [
              "@babel/preset-env",
              {
                // 按需加载
                useBuiltIns: "usage",
                corejs: {
                  version: 3,
                },
                // 指定兼容性做到浏览器哪个版本
                targets: {
                  ie: "9",
                },
              },
            ],
          ],
        },
      },
     ]

js压缩

将mode改为生产模式

压缩html

 plugins: [
    new HtmlWebpackPlugin({
      template: "./src/html/index.html",
      // 压缩
      minify:{
        // 删除空格
        collapseWhitespace:true,
        // 删除注释
        removeComments:true
      }
    })
    ]

性能优化

开发环境性能优化

打包构建速度优化 (HMR)

使用HMR(模块热替换),其作用为:当一个模块发生变化,只会重新打包这一个模块,而不是打包所有模块.这样极大的提升了构建速度.(HMR 不适用于生产环境).webpack-dev-server v4开始已经自动开启了HMR

 devServer: {
    static: { directory: resolve(__dirname, 'build') }, // 运行项目的目录:构建后的目录
    // 启动gzip压缩
    compress: true,
    port: 3000,
    // 开启HMR
    open: true,
  },

css文件:可以直接使用HMR,因为style-loader中实现了.

js文件:默认不使用HMR.如需使用,需要在js中使用HMR功能函数(且只能对非入口js文件的js文件使用).

if (module.hot) { // 说明开启了HMR
  module.hot.accept('./ha.js', () => { // 方法会监听ha.js文件的变化,一旦改变,其他不会重新打包构建,会执行后面的回调函数
    add();
  });
}

html文件:默认不使用HMR.(html也不用做HMR功能,因为单页面就只有一个html,没办法优化)

代码调试优化 (source-map)

rce-map:一种提供源代码到构建后代码映射技术(构建后代码出错,可以通过映射追踪源代码的错误)
1.source-map:外部  
误代码准确信息和源代码中错误位置

2. inline-source-map:内联(只生成一个内联source-map)
错误代码准确信息和源代码中错误位置

3. hidden-source-map:外部
错误代码准确信息,没有源代码的错误位置,只有构建后的错误位置

4.eval-source-map:内联(每个文件都生成对应的source-map,且在eval中)
错误代码准确信息和源代码中错误位置

5.nosource-source-map:外部
代码准确信息,没有任何源代码信息

6. cheap-source-map:外部   
代码准确信息,源代码中会一整行报错(不是太精确)

7.cheap-module-source-map:外部
错误代码准确信息和源代码中错误位置
 
 内联与外部的区别:
 
 1.外部生成了一个单独的文件,内联没有
 
 2.内联构建速度快(让代码体积大)
 
 
 
开发环境中:需要构建速度快,调试友好.eval-ource-map)
速度(eval>inline>cheap)
生产环境中:调试友好(source-map)
源代码是否需要隐藏(nosource-source-map/hidden-source-map)

生产环境性能优化

oneOf

正常情况下,每个文件会被rule下面的每个loader都过一遍.很多情况下都是没有必要的.使用oneOf会让以下loader只匹配一个,不会再走后面的loader了. 注意在使用oneOf时,别多配置处理同一种文件

  rules: [

      {
        oneOf: [ // 打包 css
          {
            test: /\.css$/,
            use: [
              // 创建style标签,将js中的样式资源插入添加到head中生效
              // 'style-loader',
              MiniCssExtractPlugin.loader,
              // 将 css 文件变成commonjs模块加载到js中,里面的内容是string类型
              'css-loader',
              // css兼容处理
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [['postcss-preset-env']],
                  },
                },
              },
              // 加载规则 从下到上,从右到左
            ],
          },

          // 打包 less
          {
            test: /\.less$/,
            use: [
              // 创建style标签,将js中的样式资源插入添加到head中生效
              // 'style-loader',
              MiniCssExtractPlugin.loader,
              // 将 css 文件变成commonjs模块加载到js中,里面的内容是string类型
              'css-loader',
              // 把less变为css
              'less-loader',
            ]
          }
          ]
          }
          ]

打包构建速度优化

代码运行性能优化