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代码就可以在浏览器上执行

  • 相关阅读:
    监听浏览器使用不同版本js并且处理ie兼容getElementByClassName
    超出字数部分省略(主要解决不兼容;display: -webkit-box;的浏览器)
    highcharts图表
    整理前端css/js/jq常见问题及解决方法(1)
    [转载]移动页面所需meta元素和Viewport窗口知识点
    在ie和chrome浏览器中滚动条样式的设置
    关于:before :after
    mysql备份与还原
    使用xkbeancomparator对比javabean,生成操作记录
    SSO单点登录和CAS
  • 原文地址:https://www.cnblogs.com/uimeigui/p/14133582.html
Copyright © 2011-2022 走看看