不自见,故明;不自是,故彰;不自伐,故有功;不自矜,故长;夫唯不争,故天下莫与之争
github: miniapp-shaking
上一章我们介绍了遍历json文件的方法,接下来我们介绍其他文件的遍历。
1. wxml文件的遍历
wxml
文件有三种方式可以引入外部依赖:import
,include
,wxs
,解析wxml
文件需要用到htmlparser2
,需要注意htmlparser2
解析出来的标签名全部会转化为小写字母,例如<Detail/>
,解析之后的标签是detail
。
/**
* 搜集wxml依赖
* @param file
* @returns {[string]}
*/
wxmlDeps(file) {
const deps = [];
const dirName = path.dirname(file);
const content = fse.readFileSync(file, 'utf-8');
const htmlParser = new htmlparser2.Parser({
onopentag(name, attribs = {}) {
// wxml中包括了这三种导入
if (attribs.src && (name === 'import' || name === 'include' || name === 'wxs')) {
const { src } = attribs;
let wxmlFile;
if (src.startsWith('/')) {
// 处理绝对路径
wxmlFile = path.join(this.config.sourceDir, src.slice(1));
} else {
// 处理相对路径
wxmlFile = path.resolve(dirName, src);
}
if (fse.existsSync(wxmlFile)) {
deps.push(wxmlFile);
}
}
},
});
htmlParser.write(content);
htmlParser.end();
return deps;
}
2. 遍历wxss文件
wxss文件直接使用以下正则表达式匹配即可
/@import\s+['"](.*)['"];?/g
/**
* 搜集wxss依赖
* @param file
* @returns {[]}
*/
wxssDeps(file) {
const deps = [];
const dirName = path.dirname(file);
const content = fse.readFileSync(file, 'utf-8');
// wxss导入依赖的正则匹配表达式
const importRegExp = /@import\s+['"](.*)['"];?/g;
let matched;
while ((matched = importRegExp.exec(content)) !== null) {
if (matched[1]) {
let wxssFile;
if (matched[1].startsWith('/')) {
// 处理绝对路径
wxssFile = path.join(this.config.sourceDir, matched[1].slice(1));
} else {
// 处理相对路径
wxssFile = path.resolve(dirName, matched[1]);
}
if (fse.existsSync(wxssFile)) {
deps.push(wxssFile);
}
}
}
return deps;
}
3. 遍历wxs文件
wxs只支持相对路径导入,在一章我有提到过。
/**
* 搜集wxs文件依赖
* wxs文件只支持require导入相对路径
* @param filePath
* @returns {[]}
*/
wxsDeps(filePath) {
const deps = [];
const dirname = path.dirname(filePath);
// 读取js内容
const content = fse.readFileSync(filePath, 'utf-8');
// 将代码转化为AST
const ast = parse(content, {
sourceType: 'module',
plugins: ['exportDefaultFrom'],
});
// 遍历AST
traverse(ast, {
CallExpression: ({ node }) => {
if (
node.callee.name && node.callee.name === 'require'
&& node.arguments.length >= -1
) {
const [{ value }] = node.arguments;
const jsFile = this.transformWxs(dirname, value);
if (jsFile) {
deps.push(jsFile);
}
}
},
});
return deps;
}
4. 处理静态文件
对于静态文件我们直接拷贝,以保证其相对于其它文件路径的正确性。原因第一章有过说明,这里不在重复。
至此,我们的所有文件的依赖收集的方法就已经完成了,下一章我们从主包和子包入手,分别处理这些依赖。
欲知后文请关注下一章。
连载文章链接:
手写小程序摇树工具(一)——依赖分析介绍
手写小程序摇树工具(二)——遍历js文件
手写小程序摇树工具(三)——遍历json文件
手写小程序摇树工具(四)——遍历wxml、wxss、wxs文件
手写小程序摇树工具(五)——从单一文件开始深度依赖收集
手写小程序摇树工具(六)——主包和子包依赖收集
手写小程序摇树工具(七)——生成依赖图
手写小程序摇树工具(八)——移动独立npm包
手写小程序摇化工具(九)——删除业务组代码