Webpack-CheatSheet
Webpack CheatSheet | Webpack 基础与实践清单
作为著名的打包工具,

$ npm install webpack webpack-cli webpack-dev-server --save-dev
"scripts": {
"start": "webpack-dev-server --mode development",
"build": "webpack --mode production"
},
基础配置
const config = {
// 定义入口
entry: {
app: path.join(__dirname, "app"),
},
// 定义包体文件
output: {
// 输出目录
path: path.join(__dirname, "build"),
// 输出文件名
filename: "[name].js",
// 使用 hash 作为文件名
// filename: "[name].[chunkhash].js",
},
// 定义如何处理
module: {
rules: [
{
test: /\.js$/,
use: "babel-loader",
exclude: /node_modules/,
},
],
},
// 添加额外插件操作
plugins: [new webpack.DefinePlugin()],
};
module.exports = [{
entry: './app.js',
output: ...,
...
}, {
entry: './app.js',
output: ...,
...
}]
我们代码中的
const config = {
resolve: {
alias: {
/*...*/
},
extensions: [
/*...*/
],
modules: [
/*...*/
],
},
};
资源加载
const config = {
module: {
rules: [
{
// **Conditions**
test: /\.js$/, // Match files
enforce: "pre", // "post" too
// **Restrictions**
include: path.join(__dirname, "app"),
exclude: (path) => path.match(/node_modules/),
// **Actions**
use: "babel-loader",
},
],
},
};
// Process foo.png through url-loader and other matches
import "url-loader!./foo.png";
// Override possible higher level match completely
import "!!url-loader!./bar.png";
/******/ (function(modules) { // webpackBootstrap
...
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = ((text = "Hello world") => {
const element = document.createElement("div");
element.innerHTML = text;
return element;
});
/***/ })
/******/ ]);
use: ["style-loader", "css-loader"]
开发环境
题注:本文是
路径解析
随着需求的迭代与功能的完善,我们的项目也会愈发庞大而复杂,目录层级结构也会不断深化;以
import React from "react";
import { connect } from "react-redux";
import { someConstant } from "./../../config/constants";
import MyComponent from "./../../../components/MyComponent";
import { myActionCreator } from "./../../../ducks/someReducer";
毫无疑问,这样繁多的引用不可避免地会导致代码之间耦合度的增加,使得更难以重构或者优化。在适当地模块划分的基础上,我们希望在跨模块引用时,能够以绝对路径的方式,譬如:
import React from "react";
import { connect } from "react-redux";
import { someConstant } from "Config/constants";
import MyComponent from "Components/MyComponent";
import { myActionCreator } from "Ducks/someReducer";
当然,我们并不提倡过度地使用绝对路径引入,对于相对关系固定的组件,还是应该优先使用相对路径方式引入。
Webpack
如前文介绍,resolve.alias
来自定义路径解析:
module.resolve = {
alias: {
Config: path.resolve(__dirname, "..", "src", "config"),
Components: path.resolve(__dirname, "..", "src", "components"),
Ducks: path.resolve(__dirname, "..", "src", "ducks"),
Shared: path.resolve(__dirname, "..", "src", "shared"),
App: path.join(__dirname, "..", "src"),
},
};
VSCode
开发工具的支持是不可避免地因素,值得高兴的是jsconfig.json
中配置解析规则,Auto-Import 这样的自动导入工具同样能识别这些规则:
{
"compilerOptions": {
"target": "es2017",
"allowSyntheticDefaultImports": false,
"baseUrl": "./",
"paths": {
"Config/*": ["src/config/*"],
"Components/*": ["src/components/*"],
"Ducks/*": ["src/ducks/*"],
"Shared/*": ["src/shared/*"],
"App/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"]
}
ESLint
---
settings:
import/resolver: webpack # take all defaults
或者指定文件名:
---
settings:
import/resolver:
webpack:
config: "webpack.dev.config.js"
config-index: 1 # optional, take the config at index 1
对于未使用
// .eslintrc.js
module.exports = {
settings: {
"import/resolver": {
alias: {
map: [
["babel-polyfill", "babel-polyfill/dist/polyfill.min.js"],
["helper", "./utils/helper"],
["material-ui/DatePicker", "../custom/DatePicker"],
["material-ui", "material-ui-ie10"],
],
extensions: [".ts", ".js", ".jsx", ".json"],
},
},
},
};
Jest
我们可以在
"jest": {
"moduleNameMapper": {
"^Config(.*)$": "<rootDir>/src/config$1",
"^Components(.*)$": "<rootDir>/src/components$1",
"^Ducks(.*)$": "<rootDir>/src/ducks$1",
"^Shared(.*)$": "<rootDir>/src/shared$1",
"^App(.*)$": "<rootDir>/src$1"
}
TypeScript
{
"baseUrl": ".",
"paths": {
"c-apis/*": ["src/apis/*"],
"c-models/*": ["src/models/*"],
"c-stores/*": ["src/stores/*"],
"c-utils/*": ["src/shared/*"]
}
}
构建性能优化
生产环境
压缩与版本控制
代码分割
代码分割是提升

不同于
- 新的块是在多个模块间共享,或者来自于
node_modules 目录; - 新的块在压缩之前的大小应该超过
30KB ; - 页面所需并发加载的块数量应该小于或者等于
5 ; - 初始页面加载的块数量应该小于或者等于
3 ;
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
值得一提的是,这里的initial
async
all
三个配置,上述配置即是分别针对初始initial
,那么它将忽略通过动态导入的模块包包含的第三方库代码。而
{
splitChunks: {
// 禁止默认 splitChunks 行为,防止生成 a~b.js 这样的公用包
default: false,
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
vendor: {
test: /node_modules/,
chunks: "initial",
name: "vendor",
priority: 10,
enforce: true
}
}
}
}

// Webpack 3 之后支持显式指定 Chunk 名
import(/* webpackChunkName: "optional-name" */ "./module")
.then((module) => {
/* ... */
})
.catch((error) => {
/* ... */
});
webpackJsonp([0], {
KMic: function(a, b, c) {
...
},
co9Y: function(a, b, c) {
...
},
});
如果是使用
更多关于