webpack
Basic
manifest
(function(modules) {
//webpackJsonp被挂载到全局了
window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
var moduleId, result;
for (moduleId in moreModules) {
if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
// 存储moudleId
modules[moduleId] = moreModules[moduleId];
}
}
if (executeModules) {
for (i = 0; i < executeModules.length; i++) {
result = __webpack_require__(executeModules[i]);
}
}
return result;
};
var installedModules = {};
function __webpack_require__(moduleId) {
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
var module = installedModules[moduleId] = {
exports: {}
};
// 执行。加载后也会有缓存。
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
return module.exports;
}
})([]);
可以看到 webpack 内部是一个IIFE。webpack 打包后的文件,就是通过一个个函数隔离 module 的作用域,以达到不互相污染的目的。
Module: an upgraded version of a file. There are entry modules(Each module can be considered as he root module in a tree of modules. -> ModuleGraph.) and normal modules.
A module, once created and built, contains a lot of meaningful information besides the raw source code, such as: the loaders used, its dependencies, its exports(if any), its hash and much more
Chunk: encapsulates one or module modules. The first chunks are those which defined on the Entry.
splitChunk
cacheGroupFoo: {
// The number of chunks the module must appear in
minChunks: 3,
// Number of bytes put in a chunk(i.e. the sum of the number of bytes for each constituent module)
// For example, if a chunk contains 2 modules, `x` and `w`, then `nrBytesChunk = nrBytes(x) + nrBytes(w)`.
minSize: 10,
// Which modules are to be considered
modulePathPattern: /node_modules/
}
chunks = multiple modules AKA. module belong to chunks
Based on what we've seen above, a new chunk will be created if all these conditions are met simultaneously:
- the module must belong to at least 3 chunks
- the minimum number of bytes of a chunk must be at least 10
- the modules that would lead to new chunks being created must come from the node_modules folder
default option
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
idHint: "vendors",
reuseExistingChunk: true,
test: NODE_MODULES_REGEXP,
priority: -10
},
// default: false, // or disabling default cache group
default: {
idHint: "",
reuseExistingChunk: true,
minChunks: 2,
priority: -20
},
}
},
},
the latter cache group has a greater priority and this plays an important role when a module belongs to multiple cache groups.
As a side note, a cache group inherits some options if they are not specified in the cache group itself.
chunks: 'initial/async' Async means modules that imported by import('')
babel
万能大法
options: {
presets: [
['@babel/preset-env', { loose: true, modules: 'cjs' }],
['@babel/preset-react']
],
plugins: [
[
'import',
{
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css'
}
]
]
}
注意有些使用 antd 的场景,仅引入了 antd 组件,但是没有显性引入 import 'antd/dist/antd.css';
那就肯定是原有配置了 babel-plugin-import,因为它不仅 handle 了 js 的引入,还 handle 了对应 css 的引入。
v5
Single Entry
const path = require('path');
const webpack = require('webpack');
var pkg = require('./package.json');
module.exports = {
mode: 'development',
entry: './client/index.js',
output: {
path: path.resolve(__dirname, 'static2'),
filename: 'bundle.js'
},
resolve: {
alias: {
client: path.resolve(__dirname, 'client/'),
},
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: [/(node_modules\/(?!_?(nodeMouldesToBeProcessed)))/],
loader: 'babel-loader',
options: {
presets: [['@babel/preset-env', {
loose: true,
// modules: 'cjs' // if there're some mixed use of cjs and esmodule
}], '@babel/preset-react']
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader']
},
{
test: /.(gif|jpg|jpeg|png|woff|woff2|eot|ttf|svg)$/,
type: 'asset/resource'
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.version': JSON.stringify(pkg.version),
})
],
devtool: 'cheap-source-map',
devServer: {
static: path.join(__dirname, 'client'),
compress: true,
port: 9000,
hot: true,
proxy: {
'/api': 'http://localhost:3000'
},
client: {
overlay: {
warnings: false,
errors: true
}
}
}
};
devServer: use webpack serve
to trigger. static
means where to locate index.html and other static files.
- webpack-dev-server 的 index.html 是怎么注入的?其实不存在注入,而是通过 html-webpack-plugin 在内存中生成 html,再访问这个 html,自然就有了。
- static 是什么意思?简单说来,就是 webpack-dev-server 开了一个 static-middleware 的路由作为 backup。
周边
- https://www.npmjs.com/package/tapable