8.代码分离
常用代码分离方法
- 入口起点:使用 entry 配置手动地分离代码。
- 防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。
- 动态导入:通过模块的内联函数调用来分离代码。
入口起点
- 这是迄今为止最简单、最直观的分离代码的方式。不过,这种方式手动配置较多,并有一些陷阱
- webpack.config.js
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
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')
}
};
- 缺点
- 如果入口 chunks 之间包含重复的模块,那些重复模块都会被引入到各个 bundle 中。
- 这种方法不够灵活,并且不能将核心应用程序逻辑进行动态拆分代码
防止重复
- CommonsChunkPlugin 插件可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk
- webpack.config.js
const path = require('path');
+ const webpack = require('webpack');
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
another: './src/another-module.js'
},
plugins: [
new HTMLWebpackPlugin({
title: 'Code Splitting'
})
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'common' // 指定公共 bundle 的名称。
+ })
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
- 提取结果
Hash: 70a59f8d46ff12575481
Version: webpack 2.6.1
Time: 510ms
Asset Size Chunks Chunk Names
index.bundle.js 665 bytes 0 [emitted] index
another.bundle.js 537 bytes 1 [emitted] another
common.bundle.js 547 kB 2 [emitted] [big] common
[0] ./~/lodash/lodash.js 540 kB {2} [built]
[1] (webpack)/buildin/global.js 509 bytes {2} [built]
[2] (webpack)/buildin/module.js 517 bytes {2} [built]
[3] ./src/another-module.js 87 bytes {1} [built]
[4] ./src/index.js 216 bytes {0} [built]
- 以下是由社区提供的,一些对于代码分离很有帮助的插件和 loaders
- ExtractTextPlugin: 用于将 CSS 从主应用程序中分离。
- bundle-loader: 用于分离代码和延迟加载生成的 bundle。
- promise-loader: 类似于 bundle-loader ,但是使用的是 promises
动态导入
-
对于动态导入,第一种,也是优先选择的方式是,使用符合 ECMAScript 提案 的 import() 语法。第二种,则是使用 webpack 特定的 require.ensure
-
webpack.config.js
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin"); //分离文件
module.exports = {
entry: {
index: './src/index.js'
},
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "stylse-loader",
use: "css-loader"
})
}]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Code Splitting'
}),
new ExtractTextPlugin("styles.css"),
],
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
};
- src/index.js
// 我们不再使用静态导入 lodash,而是通过使用动态导入来分离一个 chunk
// 方法1:
// function getComponent() {
// return import(/* webpackChunkName: "lodash" */ 'lodash').then(_ => {
// var element = document.createElement('div');
// element.innerHTML = _.join(['Hello', 'webpack'], ' ');
// return element;
// }).catch(error => 'An error occurred while loading the component');
// }
// 方法2:
async function getComponent() {
var element = document.createElement('div');
const _ = await import(/* webpackChunkName: "lodash" */ 'lodash');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
getComponent().then(component => {
document.body.appendChild(component);
})
bundle 分析
- 官方分析工具 https://github.com/webpack/analyse
- webpack-chart: webpack 数据交互饼图。
- webpack-visualizer: 可视化并分析你的 bundle,检查哪些模块占用空间,哪些可能是重复使用的。
- webpack-bundle-analyzer: 一款分析 bundle 内容的插件及 CLI工具,以便捷的、交互式、可缩放的树状图形式展现给用户。