webpack 代码分离

有三种常用的代码分离方法:

  • 入口起点:使用 entry 配置手动地分离代码。
  • 防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。(CommonsChunkPlugin已经从 webpack v4(代号 legato)中移除,使用SplitChunksPlugin 插件可以将公共的依赖模块提取到已有的 entry chunk 中,或者提取到一个新生成的 chunk。)
  • 动态导入:通过模块的内联函数调用来分离代码。
module.exports = {
  entry: {
    index: './src/index.js',
    another: './src/another-module.js'
  },
  plugins: [
    new HTMLWebpackPlugin({
      title: 'Code Splitting'
    })
  ],
  output: {
    filename: '[name].bundle.js',//生成分离代码
    path: path.resolve(__dirname, 'dist')
  },
optimization: {
splitChunks: {//删除重复依赖项,分离到一个单独的 chunk 中
chunks: 'all'
}
}
};
  • ExtractTextPlugin: 用于将 CSS 从主应用程序中分离。(webpack 3)(webpack 4 使用 mini-css-extract-plugin)
  • bundle-loader: 用于分离代码和延迟加载生成的 bundle。
  • promise-loader: 类似于 bundle-loader ,但是使用的是 promises。
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]
}

它会将所有的入口 chunk(entry chunks)中引用的 *.css,移动到独立分离的 CSS 文件。因此,你的样式将不再内嵌到 JS bundle 中,而是会放到一个单独的 CSS 文件(即 styles.css)当中。

多个实例

const ExtractTextPlugin = require('extract-text-webpack-plugin');

// 创建多个实例
const extractCSS = new ExtractTextPlugin('stylesheets/[name]-one.css');
const extractLESS = new ExtractTextPlugin('stylesheets/[name]-two.css');

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: extractCSS.extract([ 'css-loader', 'postcss-loader' ])
      },
      {
        test: /\.less$/i,
        use: extractLESS.extract([ 'css-loader', 'less-loader' ])
      },
    ]
  },
  plugins: [
    extractCSS,
    extractLESS
  ]
};

修改文件名

entry: {
  'js/a': "./a"
},
plugins: [
  new ExtractTextPlugin({
    filename:  (getPath) => {
      return getPath('css/[name].css').replace('css/js', 'css');
    },
    allChunks: true
  })
]

demo地址:webpack-auto-refresh

动态导入

import() 语法 来实现动态导入

module.exports = {
    mode: 'development',
    entry: {
      index: './src/index.js'
    },
    output: {
      filename: '[name].bundle.js',
      chunkFilename: '[name].bundle.js',//非入口 chunk 名称
      path: path.resolve(__dirname, 'dist')
    }
};

webpack v4.6.0+ 添加了预取和预加载的支持。

  • prefetch(预取):将来某些导航下可能需要的资源
  • preload(预加载):当前导航下可能需要资源
import(/* webpackPrefetch: true */ 'LoginModal');

这会生成 <link rel="prefetch" href="login-modal-chunk.js"> 并追加到页面头部,指示着浏览器在闲置时间预取 login-modal-chunk.js 文件。

import(/* webpackPreload: true */ 'ChartingLibrary');

在页面中使用 ChartComponent 时,在请求 ChartComponent.js 的同时,还会通过 <link rel="preload"> 请求 charting-library-chunk。

动态地加载模块。调用 import() 之处,被作为分离的模块起点,意思是,被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk 中。

import() 会返回一个 promise。

import("./math").then(math => {
  console.log(math.add(16, 26));
});

参考:https://webpack.docschina.org/guides/code-splitting/