开启辅助访问
 找回密码
 立即注册

webpack

lyglulu 回答数0 浏览数335
首先创建一台文件夹叫webpack
然后生成默认的package.json文件 npm init -y
在webpack文件夹中新建src文件,然后在src下创建index.js,hello.js,addFun.js文件
// index.js
import { sayHello } from './hello.js';

document.write(sayHello('hello'));
//webpack打包步骤
//1、从入口模块开始分析有哪些依赖,并且转换代码
//2、递归的分析其他依赖模块,分析有哪些依赖,并且转换代码
//3、生成可在浏览器端执行的bundle文件
——————————————————————————————————————
// hello.js
import { addFun } from './addFun.js'

export function sayHello(str){
    return str + addFun(1, 2);
}
——————————————————————————————————————
// addFun.js
export function addFun(a, b){
    return a + b;
}
在webpack文件夹中新建webpack.config.js,定义一下entry和output
// webpack.config.js
const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, './dist')
    }
}
在webpack文件夹中新建webpack.js 设置启动文件
// 启动webpack   node webpack.js
const Complier = require('./lib/complier.js');
const options = require('./webpack.config.js');

new Complier(options).run();
下面开始写编译文件complier.js,在webpack中新建文件夹为lib并创建complier.js文件和parser.js文件。其中需要安装一些babel的插件,如@babel/parser将代码转换为抽象语法树(AST)的插件,如@babel/traverse处理抽象语法树的插件,如@babel/core转换抽象语法树的插件和@babel/preset-env转换代码的插件
// parser.js
const fs = require('fs');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const path = require('path');
const { transformFromAst } = require('@babel/core');

module.exports = {
    // 分析模块 获得AST
    getAst: (filename) => {
        let content = fs.readFileSync(filename,'utf-8');
        return parser.parse(content,{
            sourceType: "module"
        })
    },
    // 获取依赖
    getDep: (ast, filename) => {
        const dep = {};// 保存相对路径和根路径两种信息
        traverse(ast,{
            //把符合ImportDeclaration的节点返回给我们
            ImportDeclaration({node}){
                //当前push进dep中的为相对路径
                //dep.push(node.source.value)
                const dirname = path.dirname(filename);
                //拼接成绝对路径
                const newPath = './' + path.join(dirname,node.source.value);
                dep[node.source.value] = newPath;
            }
        });
        return dep;
    },
    // 转换代码
    getCode: (ast) => {
        const { code } = transformFromAst(ast, null, {
            presets: ["@babel/preset-env"]
        });
        return code;
    }
}
——————————————————————————————————————
// complier.js
const { getAst, getDep, getCode } = require('./parser.js');
const fs = require('fs');
const path = require('path');

module.exports = class Complier{
    constructor(options){
        this.entry = options.entry;
        this.output = options.output;
        this.modules = [];
    }
    run(){
        const info = this.build(this.entry);
        this.modules.push(info);
        for(let i = 0;i<this.modules.length;i++){
            const item = this.modules;
            const { dep } = item;
            if(dep){
                for(let j in dep){
                    //递归处理依赖
                    this.modules.push(this.build(dep[j]));
                }
            }
        }
        //转换数据结构
        const obj = {};
        this.modules.forEach((item) => {
            return obj[item.filename] = {
                dep: item.dep,
                code: item.code
            }
        })
        //生成代码文件
        this.file(obj);
    }
    build(filename){
        let ast = getAst(filename);
        let dep = getDep(ast, filename);
        let code = getCode(ast);
        return {
            filename,
            dep,
            code
        }
    }
    file(code){
        // 获取输出信息  一些路径信息/dist/main.js
        const filePath = path.join(this.output.path,this.output.filename);
        const newCode = JSON.stringify(code);
        // relative为newCode里面使用require时传入的依赖路径 const a = require('./a.js')
        const bundle = `(function(graph){
            function require(module){
                function localRequire(relativePath){
                    return require(graph[module].dep[relativePath])
                }
                var exports = {};
                (function(require,exports,code){
                    eval(code)
                })(localRequire,exports,graph[module].code)
                return exports;
            }
            require('${this.entry}');
        })(${newCode})`;
        fs.writeFileSync(filePath,bundle,'utf-8')
    }
}
使用道具 举报
| 来自北京
快速回复
您需要登录后才可以回帖 登录 | 立即注册

当贝投影