跳到主要内容

Webpack 中模块混用问题

由于篇幅限制,所以本文只探讨 CommonJS 与 ES6 模块化在 Webpack 中的兼容问题

我们可以首先分别写出一个 CommonJS 的导出与 ES6 导出的文件

// CommonJS导出,文件名commonExport.cjs
function say() {
console.log("Hello World");
}
exports.say1 = say;
exports.say2 = "123";
// ES6导出,文件名esExport.js
function say() {
console.log("Hello World");
}
exports.say1 = say;
exports.say2 = "123";

接下来再分别使用 ES6 导入 CommonJS 模块,以及通过 CommonJS 模块导入 ES6 模块

//CommonJS模块导入ES6模块
const esExport = require("./esExport.js");
console.log("esExport", esExport);
//ES6导入CommonJS模块
import commonExport from "./commonExport.cjs";
console.log("commonExport", commonExport);

然后我们开始使用 webpack 进行编译,输入npm install webpack webpack-cli --save-dev,同时安装 webpack webpack-cli 两个依赖

然后创建一个webpack.config.js文件,输入

const path = require("path");
module.exports = {
mode: "none",
entry: {
cjs: "./commonIndex.cjs",
ejs: "./esIndex.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].bundle.js",
},
};

其中 mode 为none表示不进行任何优化,因为我们有两个导入都是各自独立的,可以视为两个项目,所以应该声明多个入口点entry中的对象就是声明多个入口点的,其中对象的属性名表示该入口点的 name,值为入口点文件的路径。

output 表示打包的相关处理,其中 path 告诉 webpack 应该打包到那里,而 filename 则告诉文件名应该叫什么,这里我们取名为入口点的 name 名拼接.bundle.js

然后输入npx webpack即可打包,但是如果要执行还需要引入 html,太麻烦了,我们直接让其自动创建一个 html 并且引入 js 文件,输入npm install html-webpack-plugin -D安装html-webpack-plugin插件,然后修改 webpack.config.js 文件。

我们在plugins属性上声明,其中filename表示html的文件名,而chunks表示要引入哪些文件,这个与入口点的对象属性名相同即可。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "none",
entry: {
cjs: "./commonIndex.cjs",
ejs: "./esIndex.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].bundle.js",
},
plugins: [
new HtmlWebpackPlugin({
filename: "cjs.html",
chunks: ["cjs"],
}),
new HtmlWebpackPlugin({
filename: "ejs.html",
chunks: ["ejs"],
}),
],
};

打包后得到Html通过测试,无论哪种导入都已经可以正常运行。

这是因为webpack在打包之后会对导入的语句进行转义,并且进行浏览器兼容处理

最后运行在浏览器上的引入函数实际上是一个webpack__require函数

由该函数进行模块之间的引入,webpack又做了兼容性处理,所以才可以实现原本不兼容的最后却可以正常的导入导出。