不自见,故明;不自是,故彰;不自伐,故有功;不自矜,故长;夫唯不争,故天下莫与之争
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包