vben
2020-10-18 7101587b9676c91e9079044a096df08848f1f602
提交 | 用户 | age
77db3d 1 // 修改自
31e271 2 // https://github.com/luxueyan/vite-transform-globby-import/blob/master/src/index.ts
V 3
4 // TODO 目前还不能监听文件新增及删除 内容已经改变,缓存问题?
5 // 可以使用,先不打算集成
6 import { join } from 'path';
7 import { lstatSync } from 'fs';
8 import glob from 'glob';
9 import { createResolver, Resolver } from 'vite/dist/node/resolver.js';
10 import { Transform } from 'vite/dist/node/transform.js';
11
12 const modulesDir: string = join(process.cwd(), '/node_modules/');
13
14 interface SharedConfig {
15   root?: string;
16   alias?: Record<string, string>;
17   resolvers?: Resolver[];
18 }
19
20 function template(template: string) {
21   return (data: { [x: string]: any }) => {
22     return template.replace(/#([^#]+)#/g, (_, g1) => data[g1] || g1);
23   };
24 }
25
26 const globbyTransform = function (config: SharedConfig): Transform {
27   const resolver = createResolver(
28     config.root || process.cwd(),
29     config.resolvers || [],
30     config.alias || {}
31   );
32   const cache = new Map();
33
34   const urlMap = new Map();
35   return {
36     test({ path }) {
37       const filePath = path.replace('\u0000', ''); // why some path startsWith '\u0000'?
38       try {
39         return (
40           !filePath.startsWith(modulesDir) &&
41           /\.(vue|js|jsx|ts|tsx)$/.test(filePath) &&
42           lstatSync(filePath).isFile()
43         );
44       } catch {
45         return false;
46       }
47     },
48     transform({ code, path, isBuild }) {
49       let result = cache.get(path);
50       if (!result) {
51         const reg = /import\s+([\w\s{}*]+)\s+from\s+(['"])globby(\?path)?!([^'"]+)\2/g;
52         const match = code.match(reg);
8a1bfd 53         if (!match) return code;
V 54         const lastImport = urlMap.get(path);
31e271 55         if (lastImport && match) {
V 56           code = code.replace(lastImport, match[0]);
57         }
58         result = code.replace(reg, (_, g1, g2, g3, g4) => {
59           const filePath = path.replace('\u0000', ''); // why some path startsWith '\u0000'?
60           // resolve path
61           const resolvedFilePath = g4.startsWith('.')
62             ? resolver.resolveRelativeRequest(filePath, g4)
63             : { pathname: resolver.requestToFile(g4) };
64           const files = glob.sync(resolvedFilePath.pathname, { dot: true });
65           let templateStr = 'import #name# from #file#'; // import default
66           let name = g1;
67           const m = g1.match(/\{\s*(\w+)(\s+as\s+(\w+))?\s*\}/); // import module
68           const m2 = g1.match(/\*\s+as\s+(\w+)/); // import * as all module
69           if (m) {
70             templateStr = `import { ${m[1]} as #name# } from #file#`;
71             name = m[3] || m[1];
72           } else if (m2) {
73             templateStr = 'import * as #name# from #file#';
74             name = m2[1];
75           }
76           const temRender = template(templateStr);
77
78           const groups: Array<string>[] = [];
79           const replaceFiles = files.map((f, i) => {
80             const file = g2 + resolver.fileToRequest(f) + g2;
81             groups.push([name + i, file]);
82             return temRender({ name: name + i, file });
83           });
84           urlMap.set(path, replaceFiles.join('\n'));
85           return (
86             replaceFiles.join('\n') +
87             (g3 ? '\n' + groups.map((v) => `${v[0]}._path = ${v[1]}`).join('\n') : '') +
88             `\nconst ${name} = { ${groups.map((v) => v[0]).join(',')} }\n`
89           );
90         });
91         if (isBuild) cache.set(path, result);
92       }
93       return result;
94     },
95   };
96 };
97 export default globbyTransform;