依然銜接上文,此文仿照webpack萬(wàn)物皆模塊的思想,嘗試為我們寫(xiě)的browserify引入其他模塊如css,ts等類(lèi)型文件。
流程:
- 非js文件也可以require
- 最終一起打包在chunk文件中,且對(duì)應(yīng)引入功能均可用
思路
經(jīng)典思路,即使用loader,流程如下:
1.匹配每個(gè)require函數(shù)引入路徑的后綴
2.使用對(duì)應(yīng)的loader將文件代碼處理一遍
3.其他與之前一樣
實(shí)現(xiàn)
在生成函數(shù)代碼塊時(shí)改成如下內(nèi)容
`function(){
${useLoader(wholePath, codeSplicing, pathIndexMap)}
}`
其中,useLoader如下
const { extname, resolve, dirname, basename } = require("path");
const { execSync } = require("child_process");
const fs = require("fs");
const scriptFormat = (path, code, codeSplicing, pathIndexMap) => {
return code
.trim()
.replace(/require/g, "_require")
.replace(/_require\(['\"](.*)['\"]\)/g, function (matched, $1) {
const filePath = resolve(dirname(path), $1);
codeSplicing(filePath);
return `_require(${pathIndexMap[resolve(filePath)]})`;
})
.replace(/;$/, "");
};
const loaderMap = {
js(path, codeSplicing, pathIndexMap) {
const code = scriptFormat(
path,
fs.readFileSync(path, "utf-8"),
codeSplicing,
pathIndexMap
);
return `
const module = {exports:{}};
let {exports} = module;
${code}
return module.exports
`;
},
css(path) {
const cssCode = fs.readFileSync(path, "utf-8");
return `
const style = document.createElement("style");
style.innerText = \`${cssCode}\`
document.head.appendChild(style)
`;
},
ts(path, codeSplicing, pathIndexMap) {
const filePath = `./test/temp_${basename(path, ".ts")}.js`;
try {
execSync(`tsc ${path} --outFile ${filePath}`);
} catch (error) {}
const code = scriptFormat(
path,
fs.readFileSync(resolve(filePath), "utf-8"),
codeSplicing,
pathIndexMap
);
fs.unlinkSync(resolve(filePath));
return `
const module = {exports:{}};
let {exports} = module;
${code}
return module.exports
`;
},
};
const useLoader = function (path, codeSplicing, pathIndexMap) {
const ext = extname(path).replace(/^\./, "");
const loader = loaderMap[ext];
if (!loader) throw new Error("不支持 ${loader} 文件類(lèi)型");
return loader(path, codeSplicing, pathIndexMap);
};
測(cè)試
module3.ts
const {obj} = require("./module2.js");
const weather:string = 'snow'
obj.age+=10
module.exports = {
weather
};
color.css
p {
color: rgb(79, 114, 230);
}
index.js
const { obj } = require("./module1.js");
const module2 = require("./module2.js");
const { weather } = require("./module3.ts");
require("../asserts/css/color.css");
obj.name = "jane";
obj.age += 10;
console.log(obj);
console.log(module2);
console.log(weather);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>測(cè)試文字</p>
<script src='./dist/chunk.js'></script>
</body>
</html>
打印內(nèi)容:
{ name: 'jane', age: 50 }
{ obj: { name: 'jane', age: 50 } }
snow
瀏覽器效果:
引入的ts文件,css文件均生效,且ts和js兩種格式可以互相隨意引用
總結(jié)
loader的工作本質(zhì)是通過(guò)javascript,dom,web api等使得html文件能夠作用其內(nèi)容
代碼路徑:https://github.com/a793816354/myBrowserify/tree/arrWithLoader