commonjs是通过module.exports导出模块,用require引入一个模块,原理闭包;
a.js
module.exports = "commonjs"
复制代码
b.js
let str = require('./a.js');
console.log(str);
复制代码
js实现req方法模拟coomonjs的模块导出引入
let fs = require(fs)
function req(moduleName){
let content = fs.readFileSync(moduleName);
let fn = new Function("exports","module","require","__dirname","__filename",content+"\n return module.exports")
let module = {
exports:{}
};
return fn(module.exports,module,req,__dirname,__filename);
}
复制代码
原理:commonjs就是读取文件内容,然后创建了一个匿名函数,然后将匿名函数执行结果返回。
function (exports,module,require,__dirname,__filename) {
module.exports = 'commonjs';
return moodule.exports;
}
复制代码
requirejs是通过define定义导出模块,用require引入模块。
define('name',[],function(){
return 'requirejs'
})
define('say',['name'].function(name){
return `my name is ${name}`
})
require(['say'],function(text){
console.log(text)
})
复制代码
js实现define 和require方法
let factories = {}
function define(moduleName,dependencies,factory){
factory.dependencies = dependencies;//记住对应的依赖关系
factories[moduleName] = factory;
}
function require(mods,callback){
let result = mods.map(mod=>{
let factory = factories[mod];
let exports ;
let dependencies = factory.dependencies;
require(dependencies,function(...args){//递归处理依赖关系
exports = factory.apply(null,args)
})
return exports;
})
callback.apply(null,result)
}
复制代码
webpack简易版
webpack构建可进行代码打包、压缩,可处理es6的模块化
全局安装
npm install webpack -g 不推荐(版本号问题)
复制代码
本地安装
npm init -y
npm install webpack webpack-cli -D (4.0+需要安装两个一个webpack 一个webpack-cli)
npm info +包名 查看包的信息(包括包的最新版本号)
复制代码
node8.0+ 自带了npx,npx可以直接执行文件
在node_modules中 .bin 目录 有webpack。
控制台直接npx webpack,就会把webpack文件执行,webpack默认以当前执行目录为基准,找到src下的index.js文件打包到dist目录;
webpack 新增了两种模式 mode ,可以指定开发环境打包 还是 生产环境打包,不指定默认是生产环境
npx webpack --mode development ,开发环境打包,不压缩。
npx webpack --mode production 生产环境,会压缩成1行。
复制代码
模拟webpack实现自己的一个简易脚手架;
查看webpack打包的结果,主要的代码,其中eval中的为js文件中的代码内容。
(function (modules) {
function require(moduleId) {
var module = installedModules[moduleId] = {
exports: {}
};
modules[moduleId].call(module.exports, module, module.exports, require);
return module.exports;
}
return require("./src/index.js");
})
({
"./src/a.js": (function (module, exports) {eval(""}),
"./src/index.js":(function (module, exports, require) {eval("");})
});
复制代码
脚手架名称:juejinpack
作用:将src目录下的js打包到dist目录中
1.创建包juejinpack>bin>juejinpack.js
2.初始化包juejinpack => npm init -y
3.修改package.json的bin设置 为 juejinpack.js
4.npm link将juejinpack升级为全局命令
将juejinpack软连接添加到 usr/local/bin中;
将juejinpack包添加到全局usr/local/lib/node_modules中。
5.全局就可以使用juejinpack;会把当前执行目录的src中的js进行打包。
复制代码
juejinpack.js 描述如何打包.
let entry = './src/index.js';//入口文件(webpack是读取配置文件)
let output = './dist/main.js';//出口(webpack是读取配置文件)
let fs = require('fs');
let path = require('path');
let ejs = require('ejs'); //npm install ejs -D,ejs模版
let script = fs.readFileSync(entry,'utf8');//读取入口文件
let styleLoader = function (source) {
//此处是自己实现一个简易的style-loader转换功能,source 代表样式文件中的内容
return `
let style = document.createElement('style');
style.innerText = ${JSON.stringify(source).replace(/\\r/g,'').replace(/\\n/g,'')};
document.head.appendChild(style)
`
};
// 处理模块之间依赖关系
let modules = [];
script = script.replace(/require\(['"](.+?)['"]\)/g,function () {
// ./a.js 替换为 ./src/a.js
let name = path.join('./src',arguments[1]);
// 读取依赖的文件
let content = fs.readFileSync(name,'utf8');
// ./src.index.css
if(/\.css$/.test(name)){
content = styleLoader(content)
}
// 生成modules
modules.push({
name,
content
});
return `require('${name}')`
});
//定义模版,就是webpack打包后的主要代码
let template2 =`
(function (modules) {
function require(moduleId) {
var module = {
exports: {}
};
modules[moduleId].call(module.exports, module, module.exports, require);
module.l = true;
return module.exports;
}
return require("<%-entry%>");
})
({
"<%-entry%>":
(function (module, exports, require) {
eval(\`<%-script%>\`)
})
<%for(let i=0;i<modules.length;i++){
let module = modules[i];%>,
"<%-module.name%>":
(function (module, exports, require) {
eval(\`<%-module.content%>\`)
})
<%}%>
});`;
let result = ejs.render(template2,{entry,script,modules});// result为替换后的结果,最终写到dist目录下
fs.writeFileSync(output,result);
console.log('编译成功')
复制代码