方案一
webpack-demo
|- package.json
|- webpack.common.js
|- webpack.dev.js
|- webpack.prod.js
|- server.js
|- DEV-server.js
|- /dist
|- /src
|- data.xml
|- icon.png+
|- style.css
|- my-font.woff
|- my-font.woff2
|- print.js
|- index.js
|- math.js
|- /node_modules
// index.js
import _ from 'lodash';
import './style.css';
import Icon from './icon.svg';
import Data from './data.xml';
import printMe from './print.js';
import { cube } from './math.js';
function componentPre() {
let element = document.createElement('pre');
element.innerHTML = [
'Hello webpack!',
'5 cubed is equal to ' + cube(5)
].join('\n\n');
element.classList.add('hello');
var myIcon = new Image();
myIcon.src = Icon;
element.appendChild(myIcon);
var btn = document.createElement('button');
btn.innerHTML = 'Click me and check the console!';
btn.onclick = printMe;
element.appendChild(btn);
console.log(Data);
return element;
}
function component() {
let element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
element.classList.add('hello');
var myIcon = new Image();
myIcon.src = Icon;
element.appendChild(myIcon);
var btn = document.createElement('button');
btn.innerHTML = 'Click me and check the console!';
btn.onclick = printMe;
element.appendChild(btn);
console.log(Data);
return element;
}
// document.body.appendChild(component());
let element = componentPre(); // Store the element to re-render on print.js changes
document.body.appendChild(element);
if (module.hot) {
module.hot.accept('./print.js', function () {
console.log('Accepting the updated printMe module!');
document.body.removeChild(element);
element = componentPre(); // Re-render the "component" to update the click handler
document.body.appendChild(element);
})
}
// print.js
import _ from 'lodash';
export default function printMe() {
// console.log('I get called from print.js!');
console.log('Updating print.js...' + _.join(['Another', 'module', 'loaded!'], ' '));
}
// webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 自动生成页面
const CleanWebpackPlugin = require('clean-webpack-plugin'); // 自动清理,清理dist旧文件
const webpack = require('webpack');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js',
},
optimization: { // 防止重复
splitChunks: {
chunks: 'all'
}
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Output Management'
}),
new webpack.HotModuleReplacementPlugin()
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
},
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
{
test: /\.xml$/,
use: [
'xml-loader'
]
}
],
}
};
有了optimization.splitChunks配置选项,我们现在应该看到从我们的index.bundle.js
和中删除了重复的依赖项print.bundle.js
。该插件应该注意到我们已经分离lodash
出一个单独的块并从我们的主捆绑中移除了自重
以下是社区提供的用于拆分代码的一些其他有用的插件和加载器:
mini-css-extract-plugin:用于从主应用程序中分离CSS。
bundle-loader:用于拆分代码并延迟加载生成的包。
promise-loader:类似
bundle-loader
但使用承诺。
方案二
在动态代码拆分方面,webpack支持两种类似的技术。第一种建议的方法是使用符合ECMAScript提议的import()语法进行动态导入。传统的,特定于webpack的方法是使用。让我们尝试使用这两种方法中的第一种……
import()
调用内部使用promises。如果您使用import()
较旧的浏览器,请记住使用填充程序来填充,Promise
例如es6-promise或promise- polyfill。
// webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 自动生成页面
const CleanWebpackPlugin = require('clean-webpack-plugin'); // 自动清理,清理dist旧文件
const webpack = require('webpack');
module.exports = {
entry: {
app: './src/index.js',
// print: './src/print.js',
},
// optimization: { // 防止重复
// splitChunks: {
// chunks: 'all'
// }
// },
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Output Management'
}),
new webpack.HotModuleReplacementPlugin()
],
output: {
filename: '[name].bundle.js',
// ==================================================================
chunkFilename: '[name].bundle.js', // 使用这个
// ==================================================================
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
},
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
{
test: /\.xml$/,
use: [
'xml-loader'
]
}
],
}
};
下面代码需要注意的是 import printMe from ‘./print.js’; 如果你的引入依赖将包含你所想要拆分的文件时,此文件不被拆分。并且前一个文件加载过后,import(/ webpackChunkName: “lodash” / ‘lodash’),’./print.js文件不需要引入,直接使用即可。
// index.js
// import _ from 'lodash';
import './style.css';
import Icon from './icon.svg';
import Data from './data.xml';
// import printMe from './print.js';
import { cube } from './math.js';
function getComponent() {
return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}).catch(error => 'An error occurred while loading the component');
}
getComponent().then(component => {
document.body.appendChild(component);
})
作为import()
返回承诺,它可以与async函数一起使用。但是,这需要使用像Babel这样的预处理器和Syntax Dynamic Import Babel插件。以下是如何简化代码:
async function getComponent() {
var element = document.createElement('div');
const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
getComponent().then(component => {
document.body.appendChild(component);
});