webpack-Bundler源码编写(模块分析)
2021-06-05 01:03
标签:required 相对 star expr break mod error sch lex 为了简单理解webpack原理。 新建项目:webpack_bundler word.js: message.js: index.js: bundler.js: 在命令行中执行:node bundler.js,会输出index.js的内容: 我们可以使用babel的一个第三方工具来帮我们分析代码 https://babel.docschina.org/docs/en/babel-parser: npm install @babel/parser --save 修改bundler.js后运行node bundler.js: 命令行就会输出一个抽象语法树: 接下来我们看一下program下面的body: 输出: 这样我们就可以拿到所有引入的声明来分析依赖关系,babel还给我们提供了一个模块来帮我们快速找到import节点: npm install @babel/traverse --save 修改一下bundler.js: 重新运行node bundler.js输出: 这样我们就拿到了所有的依赖,上面的source的value就是我们依赖的文件。 再稍微修改一下bundler.js: 会输出:[ ‘./message.js‘ ] 还有一个问题是我们现在拿到的文件路径是相对于src下的路径,我们在开发中需要的是跟目录下的路径,所以还需要做一点改进: 命令行输出:[ ‘./src/message.js‘ ] 但是如果我们只存绝对路径二没有相对路径的话最后打包还是会比较麻烦,所以最好是把两个路径都存下来: 命令行输出:{ ‘./message.js‘: ‘src/message.js‘ } 这就是我们想要的结果,最后只要返回就可以了: return { filename,dependencies } 浏览器无法运行这样的代码,所以我们还需要将它转换成浏览器可以运行的代码,我们还可以借助babel的一个模块: npm install @babel/core --save 还需要转换成es5: npm install @babel/preset-env --save 修改bundler.js: 命令行输出: 这就转换成浏览器可以运行的代码了。 webpack-Bundler源码编写(模块分析) 标签:required 相对 star expr break mod error sch lex 原文地址:https://www.cnblogs.com/jingouli/p/12336344.html// 目录
src
index.js
message.js
word.js
bundler.js
export const word=‘hello‘;
import {word} from ‘./word.js‘;
const message=`say ${word}`;
export default message;
import message from ‘./message.js‘;
console.log(message);
const fs=require(‘fs‘);
const moduleAnalyser=(filename)=>{
const content=fs.readFileSync(filename,‘utf-8‘);
console.log(content);
}
moduleAnalyser(‘./src/index.js‘);
import message from ‘./message.js‘;
console.log(message);
const fs=require(‘fs‘);
const parser=require(‘@babel/parser‘);
const moduleAnalyser=(filename)=>{
const content=fs.readFileSync(filename,‘utf-8‘);
console.log(parser.parse(content,{
sourceType:‘module‘ // 当我们使用ES module语法时需要加上
}));
}
moduleAnalyser(‘./src/index.js‘);
Node {
type: ‘File‘,
start: 0,
end: 58,
loc:
SourceLocation {
start: Position { line: 1, column: 0 },
end: Position { line: 3, column: 21 } },
errors: [],
program: // 表示当前运行的程序
Node {
type: ‘Program‘,
start: 0,
end: 58,
loc: SourceLocation { start: [Position], end: [Position] },
sourceType: ‘module‘,
interpreter: null,
body: [ [Node], [Node] ],
directives: [] },
comments: [] }
const ast=parser.parse(content,{
sourceType:‘module‘
});
console.log(ast.program.body);
[ Node {
type: ‘ImportDeclaration‘, // 引入的声明--import message from ‘./message.js‘;
start: 0,
end: 35,
loc: SourceLocation { start: [Position], end: [Position] },
specifiers: [ [Node] ],
source:
Node {
type: ‘StringLiteral‘,
start: 20,
end: 34,
loc: [SourceLocation],
extra: [Object],
value: ‘./message.js‘ } },
Node {
type: ‘ExpressionStatement‘, // 表达式语句--console.log(message);
start: 37,
end: 58,
loc: SourceLocation { start: [Position], end: [Position] },
expression:
Node {
type: ‘CallExpression‘,
start: 37,
end: 57,
loc: [SourceLocation],
callee: [Node],
arguments: [Array] } } ]
const fs=require(‘fs‘);
const parser=require(‘@babel/parser‘);
const traverse=require(‘@babel/traverse‘).default;
const moduleAnalyser=(filename)=>{
const content=fs.readFileSync(filename,‘utf-8‘);
const ast=parser.parse(content,{
sourceType:‘module‘
});
traverse(ast,{
ImportDeclaration({node}){
console.log(node);
}
});
}
moduleAnalyser(‘./src/index.js‘);
Node {
type: ‘ImportDeclaration‘,
start: 0,
end: 35,
loc:
SourceLocation {
start: Position { line: 1, column: 0 },
end: Position { line: 1, column: 35 } },
specifiers:
[ Node {
type: ‘ImportDefaultSpecifier‘,
start: 7,
end: 14,
loc: [SourceLocation],
local: [Node] } ],
source:
Node {
type: ‘StringLiteral‘,
start: 20,
end: 34,
loc: SourceLocation { start: [Position], end: [Position] },
extra: { rawValue: ‘./message.js‘, raw: ‘\‘./message.js\‘‘ },
value: ‘./message.js‘ } }
let dependencies=[];
traverse(ast,{
ImportDeclaration({node}){
dependencies.push(node.source.value);
}
});
console.log(dependencies);
const fs=require(‘fs‘);
const path=require(‘path‘);
const parser=require(‘@babel/parser‘);
const traverse=require(‘@babel/traverse‘).default;
const moduleAnalyser=(filename)=>{
const content=fs.readFileSync(filename,‘utf-8‘);
const ast=parser.parse(content,{
sourceType:‘module‘
});
let dependencies=[];
traverse(ast,{
ImportDeclaration({node}){
const dirname=path.dirname(filename); // ./src
const newFile=‘./‘+path.join(dirname,node.source.value);
dependencies.push(newFile);
}
});
console.log(dependencies);
}
moduleAnalyser(‘./src/index.js‘);
let dependencies={};
traverse(ast,{
ImportDeclaration({node}){
const dirname=path.dirname(filename);
const newFile=path.join(dirname,node.source.value);
dependencies[node.source.value]=newFile;
}
});
console.log(dependencies);
const fs=require(‘fs‘);
const path=require(‘path‘);
const parser=require(‘@babel/parser‘);
const traverse=require(‘@babel/traverse‘).default;
const babel=require(‘@babel/core‘);
const moduleAnalyser=(filename)=>{
const content=fs.readFileSync(filename,‘utf-8‘);
const ast=parser.parse(content,{
sourceType:‘module‘
});
let dependencies={};
traverse(ast,{
ImportDeclaration({node}){
const dirname=path.dirname(filename);
const newFile=path.join(dirname,node.source.value);
dependencies[node.source.value]=newFile;
}
});
const {code}=babel.transformFromAst(ast,null,{
presets:[‘@babel/preset-env‘]
});
console.log(code); // 浏览器可以运行的代码
return {
filename,dependencies,code
}
}
moduleAnalyser(‘./src/index.js‘);
"use strict";
var _message = _interopRequireDefault(require("./message.js"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
console.log(_message["default"]);
上一篇:pyjsonrpc的使用
下一篇:webpack-性能优化