Webpack基础

48 阅读3分钟

为什么需要打包工具?

  • 代码编译:React/Vue框架、ES6模块化语法、Less/Sass等css预处理器
  • 代码压缩:减小包大小
  • 兼容性处理:ES5兼容,浏览器兼容等
  • 提升代码性能:分包加载
  • ...

有哪些打包工具?

  • Gulp
  • Grunt
  • Webpack
  • Rollup
  • Vite
  • Esbuild
  • ...

Demo使用

  • 安装webpack webpack-cli
  • 可以npx直接在命令行启动,或者在package.json中配置命令(调用node_modules中.bin目录)
  • 直接在index.html中引用es6代码是不行的,需要通过webpack转换(或者script使用type=module)
  • js文件后缀是webpack处理的,script引用时需要完整路径

npx webpack ./src/main.js -mode=development 注意development模式下,只编译了es6模块化语法,但是箭头函数、展开操作符...并未编译,且代码未压缩; 默认打包到dist目录

npx webpack ./src/main.js -mode=production production模式下,es6模块化语法、箭头函数、展开操作符...并未编译,且代码已压缩;

且打包后的文件使用的匿名函数进行包裹,避免命名冲突

(()=>{"use strict";console.log(3),console.log([1,2,3,4].reduce(((o,e)=>o+e),0))})();

5大概念

  • 入口:webpack构建模块依赖图的起点
  • 输出:打包后资源的输出位置
  • loader: webpack默认只能识别js和json文件,对于其他类型的文件,需要通过loader进行转换webpack可处理的模块,进行后续处理。loader执行顺序为从右向左依次执行
  • plugins: 用于执行范围更广的任务,如打包优化,资源管理,注入环境变量
  • 模式:开发模式和生产模式

使用配置文件

  • npx webpack --config webpack.config.js
  • 配置文件是在nodejs环境运行的,使用module.exports导出

开发环境自动化:监听文件的更改并重新打包。需要注意的是devServer的打包资源是运行在内存中的,并没有打包到当前目录。

devServer: {
    host: 'localhost',
    port: 3000,
    open: true
},

处理css

  • css-loader可以将css提取到commonjs模块
  • style-loader 可以将模块中的css通过style标签注入到html
  • less-loader 将less转为css
  • sass-loader 将sass, scss转为css
  • mini-css-extract-plugin插件 将style中css单独提取成css文件中(用于替代style-loader)
  • postcss css样式兼容处理(package.json中的browserslist字段用于指明浏览器兼容范围)
  • css-minimizer-webpack-plugin css压缩
rules: [
  {
    test: /\.css$/i,
    // use: ['style-loader', 'css-loader']
    use: [MiniCssExtractPlugin.loader, "css-loader"],

  },
  {
        test: /\.less$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: ['postcss-preset-env'], // 兼容性问题处理
              },
            },
          },
          'less-loader',
        ],
      },
      {
        test: /\.s[ac]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: ['postcss-preset-env'], // 兼容性问题处理
              },
            },
          },
          'sass-loader',
        ],
      },
]

plugins: [
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
optimization: {
    // css压缩
    minimizer: [new CssMinimizerPlugin()]
  },

css-loader将css转换成commonjs模块

style-loader将css commjs模块插入style

处理图片

webpack内置可处理,

  • Rule.parser.dataUrlCondition.maxSize 可以配置资源大小,当资源小于该值时,使用base64编码,减少服务器请求(注意当图片较大时,转化成base64的成本也会更高,如200kb -> 400kb,得不偿失)

  • generator可以修改文件输出的目录,避免打包后的资源文件夹混乱

  • hash:10 去哈希值的前10位即可,避免文件名称太长

{
    test: /.(png|jpe?g|webp|gif|svg)$/i,
    type: 'asset',
    parser: {
      dataUrlCondition: {
        maxSize: 10 * 1024 // 10kb
      }
    },
    generator: {
      filename: 'static/[hash:10][ext][query]'
    }
}

处理字体资源

asset/resource类型资源不会转化为base64,保持文件原样输出

@font-face {
  font-family: "iconfont"; /* Project id 3375413 */
  src: url('../assets/fonts/iconfont.woff2') format('woff2'),
       url('../assets/fonts/iconfont.woff') format('woff'),
       url('../assets/fonts/iconfont.ttf') format('truetype');
}
{
    test: /.(ttf|woff2?)$/i,
    type: 'asset/resource',
    generator: {
      filename: 'static/fonts/[hash:10][ext][query]' // 指定字体资源输出目录
    }
  }

js资源处理

  • 生产模式默认已压缩

  • Eslint

    • 可以单独在.eslintrc.js文件中配置,也可以在package.json的eslintConfig中配置(eslintrc中的优先级高于package.json)
    • eslintrc可以跨层级配置,子目录的eslint是根目录eslintrc和子目录的eslintrc的组合,发生冲突时,以子目录为准
    • package.json的eslint配置也是全目录生效的
    • 配置webpack的eslint插件,在打包时可以监控eslint错误,打包失败
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
plugins: [
    new ESLintWebpackPlugin({
      // eslint检查目录
      contenxt: path.resolve(__dirname, 'src')
    })
],
  • babel
    • 将ES6语法转化为向后兼容的js语法,以便在旧版本浏览器中运行
    • 可以单独写在babel配置文件中,或者写在webpack.config.js、package.json中
module.exports = {
  presets: ['@babel/preset-env'],
  // 支持 ?.??
  plugins: ['@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-nullish-coalescing-operator']
}
  {
    test: /.m?js$/i,
    exclude: /(node_modules|bower_components)/,
    loader: 'babel-loader'
    // use: {
    //   loader: 'babel-loader',
    //   options: {
    //     presets: ['@babel/preset-env']
    //   }
    // }
  }

html资源处理

自动生成html文件,并将打包后的文件自动注入;生产模式默认已压缩

const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
    new HtmlWebpackPlugin({
      // 指定html模板,否则使用默认模板
      template: path.resolve(__dirname, 'public/index.html')
    })
],