zoukankan      html  css  js  c++  java
  • webpack原理分析之编写一个打包器

    一、引入依赖

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

    二、形成AST抽象语法树,分析模块的代码和依赖路径

    function moduleAnalyser(filename) {
        const content = fs.readFileSync(filename, 'utf-8');
        const ast = parser.parse(content, {
            // parse in strict mode and allow module declarations
            sourceType: "module",
        });
        const dependencies = {};
        traverse(ast, {
            ImportDeclaration({ node }) {
                // dependencies.push(node.source.value)
                const dirname = path.dirname(filename)
                const newFile = './' + path.join(dirname, node.source.value)
                dependencies[node.source.value] = newFile
            }
        })
        // console.log(ast.program)
        // console.log(dependencies)
        const { code } = babel.transformFromAst(ast, null, {
            presets: ["@babel/preset-env"]
        });
        return {
            filename,
            dependencies,
            code
        }
    }
    

    三、形成模块间的依赖图谱

    const makeDependenciesGraph = (entry) => {
        const entryModule = moduleAnalyser(entry)
        const graphArry = [entryModule]
        for (let i = 0; i < graphArry.length; i++) {
            const item = graphArry[i];
            // console.log(item,123)
            const { dependencies } = item;
            if (dependencies) {
                for (let j in dependencies) {
                    graphArry.push(
                        moduleAnalyser(dependencies[j])
                    )
                }
            }
        }
        const graph = {}
        graphArry.forEach(item => {
            graph[item.filename] = {
                dependencies: item.dependencies,
                code: item.code
            }
        })
        return graph
    }
    

    四、代码生成

    const generateCode = (entry) => {
        const graph = JSON.stringify(makeDependenciesGraph(entry));
        return `
            (function(graph){
                function require(module){
                    function localRequire(relativePath){
                        return require(graph[module].dependencies[relativePath])
                    }
                    var exports={};
                    (function(require,exports,code){
                        eval(code)
                    })(localRequire,exports,graph[module].code);
                    return exports;
                };
                require('${entry}');
            })(${graph})
        `;
    }
    const code = generateCode('./src/main.js')  //这个就是你项目的入口文件
    console.log(code)
    

    最后生成的code代码就可以在浏览器上执行

  • 相关阅读:
    自定义IP原来如此简单
    [转]如何在NIOS II中读写EPCS剩余空间
    坏了的芯片居然又好了一片,太神奇了
    今天报废两片EP3C5E144
    Quartus II 订购版 v10.1 正式推出下载
    发现用JTAG下载程序到EPCS比用AS方式下载速度快
    如何解决No EPCS layout data looking for section [EPCSXXXXXX]
    QII丰衣足食
    Why does my Cyclone III FPGA fail to access the EPCS device using the EPCS Controller module?
    <转载>在.NET中基于Windows消息的IPC实现
  • 原文地址:https://www.cnblogs.com/uimeigui/p/14133582.html
Copyright © 2011-2022 走看看