webpack

95 阅读3分钟

1、 本地项目没有全局安装webpack,在项目上想要调用webpack可以使用命令

npx webpack

效果等同于 全局安装webpack之后,再执行 webpack

通常会在package.json中配置script,如

script: {
    "build": "webpack"
}

在命令行输入npm run build也会生效,这是因为npm命令类似npm,会优先在当前目录里查找webpack

2、 可以使用--config 指定webpack的配置文件,默认是webpack.config.js

webpack --config webpack.dev.js

3、entry: './index.js'是对entry: { main: './index.js' }的简写

4、mode: 'development' | 'production' 用来区分打包策略,development是开发环境模式,代码不会压缩

5、module用来配置各种资源(如 css jpg等)的打包策略

module: {

    rules: [{

      test: /\.jpg$/, 

      user: 'file-loader'

    }]

}

每个loader都有自己的配置下,去官网查看对应loader即可

6、file-loader负责将资源复制到output指定的文件夹下,并且将资源重命名等操作 url-loader类似file-loader,但是他还可以将文件转换为base64

7、css-loader会帮助梳理css,多个css文件会被他梳理成一个css

8、babel-loader 功能主要是建立webpack和babel之间做打通,本身不会对语法做处理

babel-core babel的核心,可以将代码转换成AST树,再将AST树转成其他形式

babel-preset-env 包含各版本如ES6 ES7的语法规则,babel根据这些规则来输出

babel-polyfill js垫片,打包后会增加打包文件的体积

业务代码打包:

入口文件引入polyfill import "@/babel/polyfill";

{

  test: /\.js$/,

  exclude: /node_modules/,

  loader: "babel-loader",

  options: {

      presets:[

          targets: { chrome: "67" },

          ["@babel/preset-env", { useBuiltIns: "usage" }]

      ]

  }

}

库代码打包:

options: {

    plugins: [

        ["@babel/plugin-transform-runtime",{

           "corejs":2, //需要安装runtime-corejs2

           "helpers":true,

           "regenerator":true,

           "useESModules":false

        }]

    ]

}

babel/polyfill是全局引入的形式做垫片,这样会污染全局环境

plugin-transform-runtime则是以闭包的形式

options内容过多的话,和已将里面内容提取出来放到 .babelrc 或者 babel.config.js

更多配置查看babel官网

9、treeShaking

development: webpack设置 optimization: { usedExports: true }, 同时在package配置:

sideEffects: ["@babel/polly-fill", "*.css"] // 对没有export的文件不做shaking

实际打包结果不会被删除,但是会加上注释,只有production才会被真正删除

production: 可以删除usedExports: true

10、code spliting

同步代码 异步代码分割可以参考这里的配置:webpack.js.org/plugins/spl…

optimization: {
    splitChunks: {
      chunks: "all",
      minSize: 1024,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          name (module, chunks, cacheGroupKey) {
            console.log(module.identifier())
            const moduleFileName = module
              .identifier()
              .split(/[/\\]/)
              .pop()
              .replace(/\..*$/, '');
            const allChunksNames = chunks.map((item) => item.name).join('~');
            return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`;
          }
        },
        default: {
          minChunks: 1,
          priority: -20
        }
      }
    },
  }

同步代码分割 利用浏览器缓存 用来提升二次请求之后的加载时间

异步代码 配合 preFetching 可以提升首屏加载速度,preFetching:

import(/* webpackPrefetch: true */ 'lodash').then((lodash) => {

    // code: lodash.join(....)

})

11、打包分析 analyse 见官网

12、css提取

使用 MiniCssExtractPlugin配合optimization使用:

optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: "styles",
          type: "css/mini-extract",
          chunks: "all",
          enforce: true,
        },
      },
    }
}

13、webpack 环境变量

a、package.json:不传值默认为true,此时production=true

script: { "build": "webpack --env.production" }

webpack.config.js:

module.export = (env) => {
    if (env && env.production) {
        return merge(baseConfig, productionConfig)
    } else {
        return merge(baseConfig, developmentConfig)
    }
}

b、也可以

script: { "build": "webpack --env production" }

webpack.config.js:

module.export = (production) => {
    if (production) {
        return merge(baseConfig, productionConfig)
    } else {
        return merge(baseConfig, developmentConfig)
    }
}

c、赋值:

script: { "build": "webpack --env.production=abc" }

webpack.config.js:

module.export = (env) => {
    if (env && env.production === 'abc') {
        return merge(baseConfig, productionConfig)
    } else {
        return merge(baseConfig, developmentConfig)
    }
}

14、打包library

在config文件使用externals指定不需要一起打入的包:

externals: "lodash"

externals: ["lodash", "dayjs"]

output指定输出类型和导出名:

output: {
    library: "myLibrary",
    libraryTarget: "umd"
}

打包完成后,修改package.json:

main: "./dist/bundle.js"  // 你的打包结果

npm adduser npm publish即可发布npm包

15、webpack打包速度优化

a、尽可能使用较新版本的node npm yarn

b、尽量减少使用loader

c、尽量使用官方推荐的plguin,保证性能

d、不要过多使用 resolve.extensions resolve.mainFiles resolve.alias 处理文件扩展

e、开发环境 借助 webpack.DllPlugin webpack.DllRefrencePlugin AddAssetsHtmlWebpackPlugin 提前抽离第三方模块,减少对第三方模块重复打包

f、合理配置source-map

g、使用stats analyse做打包分析

16、自定义loader:

myLoader.js:

module.export = function (source) {
  this.query // loader options
  return source + '/* myLoader */'
}

webpack.config.js:

module: {
  rules: [{
    test: /\.js$/
    use: [{
      loader: path.join(__dirname, 'myLoader.js'),
      options: { name: 'asd' }
    }]
  }]
}