preface
Generally our front-end engineering is unable to do without Webpack, we do not have too much resistance to the principle of Webpack, now to manually implement a very simple Webpack, a preliminary understanding of the construction process of Webpack.
The use of webpack4. X
1. After NPM init -y, install webpack webpack-CLI
NPM I [email protected] [email protected] -d
2. Create webpack.config.js, index.js, greeting.js
// webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index.js'.mode: 'development'.output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'}}// index.js
import { greeting } from './greeting.js'
document.write(greeting('Jane'))
// greeting.js
export function greeting(name) {
return 'hello ' + name
}
Copy the code
3. Build packaged, compact code
(function(modules) {
var installedModules = {}; // Cache dependency
// Implement the require method.
function __webpack_require__(moduleId) {
// The module is already required, using the cache directly.
if(installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
var module = installedModules[moduleId] = {
i: moduleId,
l: false.exports: {}};// recursively call require to build the dependency tree
modules[moduleId].call(module.exports, module.module.exports, __webpack_require__);
module.l = true;
// Returns the result of reuqire
return module.exports;
}
// Start from the entry file.
return __webpack_require__(__webpack_require__.s = "./src/index.js"); ({})"./src/greeting.js": function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function greeting(name) { return 'hello ' + name}
},
"./src/index.js": function(module, __webpack_exports__, __webpack_require__) {
"use strict";
var _greeting_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/greeting.js");
document.write(Object(_greeting_js__WEBPACK_IMPORTED_MODULE_0__["greeting"]) ('Jane'))}});Copy the code
The realization of the webpack
Business code
The SRC code and webpack.config.js are the same as above
// webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index.js'.mode: 'development'.output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'}}// index.js
import { greeting } from './greeting.js'
document.write(greeting('Jane'))
// greeting.js
export function greeting(name) {
return 'hello ' + name
}
Copy the code
The implementation code
Create a lib folder to hold the WebPack implementation code
index.js
const Compiler = require('./compiler')
const options = require('.. /webpack.config.js')
const compiler = new Compiler(options).run()
Copy the code
parse.js
npm i @babel/preset-env babel-core babel-preset-env babel-traverse babylon
- The string is first read through FS and converted into an AST tree through the Babel plug-in
- Traverse to get the path of the REQUIRE in the AST
- Convert the AST syntax tree to ES5 code via babel-core
const fs = require('fs')
// Convert string code to AST
const babylon = require('babylon')
// Get each module dependency
const traverse = require('babel-traverse').default
// Convert ast code to JS code
const { transformFromAst } = require('babel-core')
module.exports = {
getAST: (path) = > {
const source = fs.readFileSync(path, 'utf-8')
return babylon.parse(source, {
sourceType: 'module'})},getDependencies: (ast) = >{
const dependencies = []
traverse(ast, {
ImportDeclaration: ({node}) = >{
dependencies.push(node.source.value)
}
})
return dependencies
},
transform: (ast) = >{
const {code} = transformFromAst(ast,null, {presets: ['env']})return code
}
}
Copy the code
compiler.js
- Start building from the entry file
- Generate entry files generate three types of data, AST, ES5 code, dependent paths
- Recursively generate these three types of data based on their dependent paths and collect them all into a Modules array
- Finally, the file packed with parameter webpack4.x is stored in an object with the file path as the key and the module code source as the value, passing in the self-executing function as an argument.
const {getAST, getDependencies, transform}= require('./parse')
const path = require('path')
const fs = require('fs')
module.exports= class Compiler {
constructor(options) {
// Get configuration parameters
const { entry, output } = options
this.entry = entry
this.output = output
this.modules = []
}
/ / run
run(){
// Build from the entrance
const entryModule = this.buildModule(this.entry, true)
this.modules.push(entryModule)
this.modules.map(_module= >{
_module.dependencies.map(dependency= >{
this.modules.push(this.buildModule(dependency))
})
})
this.emitFiles()
}
// Build a module that generates THE ES6 code into an AST, generates the ES5 code from the AST tree, and returns the dependencies
buildModule(filename, isEntry){
let ast
if(isEntry) {
ast = getAST(filename)
} else {
const absoultePath = path.join(process.cwd(), './src',filename)
ast = getAST(absoultePath)
}
return {
filename,
dependencies: getDependencies(ast),
source: transform(ast)
}
}
// After the dependency tree is generated, output to the specified directory
emitFiles(){
const outputpath = path.join(this.output.path, this.output.filename)
const list = this.modules.map(_module= >{
return (`
'${_module.filename}': function(module, exports, require){
${_module.source}
}
`)})let modules = list.join(', ')
const bundle = `(function(modules){
var installedModules = {}
function __webpack_require__(filename){
if(installedModules[filename]) {
return installedModules[filename].exports
}
var module = installedModules[filename] = {
i: filename,
l: false,
exports: {}
}
modules[filename].call(module.exports, module, module.exports, __webpack_require__)
module.l = true
return module.exports
}
__webpack_require__('The ${this.entry}') ({})${modules}}) `;
console.log(bundle);
fs.writeFileSync(outputpath, bundle, 'utf-8')}}Copy the code
The generated code
node ./lib/index.js
(function(modules){
var installedModules = {}
function __webpack_require__(filename){
if(installedModules[filename]) {
return installedModules[filename].exports
}
var module = installedModules[filename] = {
i: filename,
l: false.exports: {}
}
modules[filename].call(module.exports, module.module.exports, __webpack_require__)
module.l = true
return module.exports
}
__webpack_require__('/Users/openlee/Desktop/simplepack/src/index.js') ({})'/Users/openlee/Desktop/simplepack/src/index.js': function(module.exports.require){
"use strict";
var _greeting = require("./greeting.js");
document.write((0, _greeting.greeting)('Jane')); },'./greeting.js': function(module.exports.require){
"use strict";
Object.defineProperty(exports."__esModule", {
value: true
});
exports.greeting = greeting;
function greeting(name) {
return 'hello '+ name; }}})Copy the code
The end of the
Finally, welcome to pass by the old iron people praise ~