webpack手写 准备工作
从这节开始,来手写一个webpack。
本节的内容
- 先看一下webpack的打包结果,看是如何把commonjs的node写法的代码,打包之后能在浏览器运行的
- 新建基础项目,本地连接一个自建库,npm link
- 自建库模拟 npx webpack 打包,先尝试把命令运行出来
准备空项目
空项目目录为 webpack-dev-3
新建a.js
// webpack\webpack-dev-3\src\a.js
let b = require('./base/b.js')
module.exports = 'aaa' + b // aaabbb
新建b.js
// webpack\webpack-dev-3\src\base\b.js
module.exports = 'bbb'
新建index.js
// webpack\webpack-dev-3\src\index.js
let str = require('./a.js')
console.log(str); // aaabbb
初始化package.json
yarn init -y
安装webpack的包
yarn add webpack@^4.32.2 webpack-cli@^3.3.2 -D
添加配置文件 webpack.config.js
// webpack\webpack-dev-3\webpack.config.js
let path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
打包,看一下打包结果 npx webpack,把多余的代码删除掉,只留一下核心的代码,一会写webpack的时候作为模板,往里填充内容就可以了。
(function (modules) { // webpackBootstrap
// The module cache
var installedModules = {};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
};
// Execute the module function
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// Flag the module as loaded
module.l = true;
// Return the exports of the module
return module.exports;
}
// Load entry module and return exports
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
({
"./src/a.js":
(function (module, exports, __webpack_require__) {
eval("// webpack\\webpack-dev-3\\src\\a.js\r\nlet b = __webpack_require__(/*! ./base/b.js */ \"./src/base/b.js\")\r\nmodule.exports = 'aaa' + b // aaabbb\n\n//# sourceURL=webpack:///./src/a.js?");
}),
"./src/base/b.js":
(function (module, exports) {
eval("// webpack\\webpack-dev-3\\src\\base\\b.js\r\nmodule.exports = 'bbb'\n\n//# sourceURL=webpack:///./src/base/b.js?");
}),
"./src/index.js":
(function (module, exports, __webpack_require__) {
eval("// webpack\\webpack-dev-3\\src\\index.js\r\nlet str = __webpack_require__(/*! ./a.js */ \"./src/a.js\")\r\nconsole.log(str); // aaabbb\n\n//# sourceURL=webpack:///./src/index.js?");
})
});
这个打包的文件,我们在之前已经看过了,参考 webpack打包出的文件解析
实际上就是自己写了一个webpack_require方法,根据入口文件,依次加载每个模块的代码,最终的结果都挂载到了module.exports上。
每当加载一个模块的时候,都会调用这个方法,然后遇见一个调用一个,当没有再继续调用模块时,再往上返回结果 module.exports。
我们运行结果,发现正常输出了 aaabbb。
在外部新建自己的打包库,模拟 npx webpack 指令打包
新建打包库,链接到全局
打包库命名为 cheny-pack
,所以模拟出的指令就是 npx cheny-pack
初始化package.json
yarn init -y
在node的package.json文件配置bin,可以运行自定义的文件
修改package.json
// webpack\cheny-pack\package.json
{
"name": "cheny-pack",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"bin": {
"cheny-pack": "./bin/cheny-pack.js"
}
}
新建cheny-pack.js
#! /usr/bin/env node
// webpack\cheny-pack\bin\cheny-pack.js
// 最顶部的注释表示,这个文件的使用node运行
console.log('start');
然后将这个包链接到全局上
npm link
这个指令,会在全局下生成 bin中配置的命令,然后执行这个文件
在需要打包的项目下,链接刚才link的指令
在webpack-dev-3项目中,链接刚才的指令,模拟打包,相当于把这个指令链接到了本地上
npm link cheny-pack
然后就可以使用 npx cheny-pack 指令来运行我们自定义的打包模块了
运行一下试试
# webpack\webpack-dev-3
npx cheny-pack
自定义指令已经生效,我们尝试修改一个打包库的代码,指令输出结果也随之改变
修改
#! /usr/bin/env node
// webpack\cheny-pack\bin\cheny-pack.js
// 最顶部的注释表示,这个文件的使用node运行
console.log('start 1111');
重新运行 npx cheny-pack
总结
本节模拟了 npx webpack 指令,本地自定义打包库。
自定义打包库,在package.json中配置
json{ "name": "cheny-pack", "version": "1.0.0", "main": "index.js", "license": "MIT", "bin": { "cheny-pack": "./bin/cheny-pack.js" } }
指定运行文件使用node执行
js#! /usr/bin/env node // webpack\cheny-pack\bin\cheny-pack.js // 最顶部的注释表示,这个文件的使用node运行 console.log('start');
将打包库链接到全局,建立了一个映射关系
shellnpm link
在需要打包的项目中,将全局打包库再链接到本项目中
shellnpm link cheny-pack
然后就可以使用 npx xxx,来运行打包库了
shellnpm cheny-pack
参考
https://www.bilibili.com/video/BV1a4411e7Bz?p=33&spm_id_from=pageDriver