因为 javascript 可以运行在服务端和客户端,所以 webpack 有多目标构建方案。
注意:webpack 的 target 属性和 output.libraryTarget 这两个是没有联系的。
使用
index.js
const fs = require('fs');
const path = require('path');
console.log(fs.toString());
console.log(path.toString());
console.log('run in node');
webpack.config.js
var {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
target: 'node',
entry: {
index: './index.js',
},
output: {
publicPath: '',
path: __dirname + '/dist',
filename: '[name].js'
},
plugins: [
new CleanWebpackPlugin()
]
}
打包后代码片段
({
"./index.js": (function (module, exports, __webpack_require__) {
eval(`
const fs = __webpack_require__(/*! fs */ \"fs\");\r\n
const path = __webpack_require__(/*! path */ \"path\");\r\n
console.log(fs.toString());\r\n
console.log(path.toString());\r\n
console.log('run in node');\n\n//# sourceURL=webpack:///./index.js?`);
}),
"fs": (function (module, exports) {
eval(`
module.exports = require(\"fs\");\n\n
//# sourceURL=webpack:///external_%22fs%22?`);
}),
"path": (function (module, exports) {
eval(`
module.exports = require(\"path\");\n\n
//# sourceURL=webpack:///external_%22path%22?`);
})
});
可以发现,配置 target 为 ‘node’ 后,如果使用了 node 内置的模块,webpack 不会将他们引入进来,而是保留原始引入语句。
多目标构建
webpack 的构建可以有多个目标。
index.js
const fs = require('fs');
const path = require('path');
console.log(fs.toString());
console.log(path.toString());
console.log('index.js');
webpack.config.js
const serverConfig = {
mode: 'development',
target: 'node',
entry: {
index: './index.js',
},
output: {
publicPath: '',
path: __dirname + '/dist',
filename: '[name].server.js'
}
}
const clientConfig = {
mode: 'development',
target: 'web', // 默认就是 web
entry: {
index: './index.js',
},
node: {
fs: 'empty', // false | true | "mock" | "empty"
path: 'empty' // false | true | "mock" | "empty"
},
output: {
publicPath: '',
path: __dirname + '/dist',
filename: '[name].client.js'
}
}
module.exports = [clientConfig,serverConfig];
以上配置会打印两份代码,一份用于客户端,一份用于服务端,其中客户端多了 node 选项配置,上述配置会将引入 fs 和 path 对应的空模块(打包后发现该模块是 “\n\n” )。
./dist/index.client.js (代码片段)
"../../../../../node/yarn/yarn_global/node_modules/node-libs-browser/mock/empty.js":
(function(module, exports) {
eval("\n\n//# sourceURL=webpack:///D:/node/yarn/yarn_global/node_modules/node-libs-browser/mock/empty.js?");
}),
"./index.js":
(function(module, exports, __webpack_require__) {
eval(`
const fs = __webpack_require__(/*! fs */ \"../../../../../node/yarn/yarn_global/node_modules/node-libs-browser/mock/empty.js\");\r\n
const path = __webpack_require__(/*! path */ \"../../../../../node/yarn/yarn_global/node_modules/node-libs-browser/mock/empty.js\");\r\n
console.log(fs.toString());\r\n
console.log(path.toString());\r\n
console.log('run in node');\n\n
//# sourceURL=webpack:///./index.js?`);
})
引入的 empty.js 它就是一个空文件…
webpack4 的 node 选项的模块对应的值有如下几种。
- true - 引入适用于浏览器的 node 的对应内置模块;
- false - 报错,无法解析 node 的内置模块;
- ‘mock’ - 在全局安装的目录下引入 node-libs-browser 中 mock 文件夹下的对应的模块,没有就报错;
- ‘empty’ - 在全局安装的目录下引入 node-libs-browser 中 mock 文件夹下的 empty.js;