实现一个简易版webpack

Posted amiezhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现一个简易版webpack相关的知识,希望对你有一定的参考价值。

现实 webpack 的打包产物

大概长这样(只把核心代码留下来):

技术图片

 

 

实现一个简版的webpack

依葫芦画瓢,实现思路分2步:

1. 分析入口文件,把所有的依赖找出来(包括所有后代的依赖)

2. 拼接出类似上面的立即执行函数

找依赖

const fs = require(‘fs‘);
const path = require(‘path‘);
const parser = require(‘@babel/parser‘);
const traverse = require(‘@babel/traverse‘).default;
const  transformFromAST  = require(‘@babel/core‘);

// 分析一个文件,转成CommonJS Module,并找出它的依赖
function readCode(filePath) 
    // 读取文件字符串
    const content = fs.readFileSync(filePath, ‘utf-8‘);
    // 语法解析成 AST
    const ast = parser(content, 
        sourceType: ‘module‘
    )
    // 获取本文件的依赖
    const dependiences = [];
    // 遍历 AST,每当触发依赖钩子,就往依赖数组添加
    traverse(ast, 
        ImportDeclaration(node) 
            // 把对应的以来路径存起来
            dependiences.push(node.source.value)
        
    )
    // 把 es6 转成 es5 字符串
    // 最重要的是把 esModule 的 import export,转成 es5 能认识的 commonJs写法
    const  code  = transformFromAST(ast, null, 
        presets: [‘@babel/preset-env‘]
    )
    return 
        filePath,
        code,
        dependiences
    


// 广度优先算法,深入找出所有的依赖
function getAllDependencies(filePath) 
    const entryObj = readCode(filePath);
    const dependencies = [entryObj];
    for (const dependency of dependencies) 
        const curDirname = path.dirname(dependency.filePath)
        for (const relativePath dependency.dependencies) 
            const absolutePath = path.join(curDirname, relativePath);
            const child = readCode(absolutePath);
            child.relativePath = relativePath;
            dependencies.push(child);
        
    
    return dependencies;

ps: 我们用的是babel的配套工具来做语法分析和转化,但是真正的webpack用的是webassemblyjs的配套工具

技术图片

 

 

拼写立即执行函数

function bundle(fileName) 
    const dependencies = getAllDependencies(fileName);
    const modulesStr = ‘‘;
    dependencies.forEach(dependency => 
        const key = dependency.relativePath || dependency.filePath;
        modulesStr += `‘$key‘: function(module, exports, require) 
            $ dependency.code 
        `
    )
    return `(function(modules) 
        const installedModules = ;
        function require(id) 
            // 解决循环依赖
            if (installedModules[id]) 
                return installedModules[id].exports;
            
            var module = installedModules[id] = exports: ;
            modules[id].call(module.exports, module, module.exports, require);
            return module.exports;
        
        return require(‘$fileName)
    )($modulesStr)`

 

以上是关于实现一个简易版webpack的主要内容,如果未能解决你的问题,请参考以下文章

手写简易版Promise

使用 LinkedBlockingQueue 实现简易版线程池

简易版dubbo实现

简易版dubbo实现

简易版dubbo实现

简易版dubbo实现