zhen's blog

编译思想,编译人生

阿里低代码引擎物料开发windows下路径问题临时处理

阿里低代码引擎物料开发windows下路径问题临时处理

使用阿里低代码进行物料开发过程中,官方文档推荐使用macOS、Linux或者windows下的WSL,其原因在于物料开发脚手架在对开发组件进行物料相关内容打包的时候会将路径字符串写入到生成文件中,这个过程会使用@alifd/build-plugin-lowcode插件里面的脚本代码进行。而如果直接使用的windows开发,会发现生成过程会报类似如下错误:

1
2
(undefined) ./.tmp/view.js
Module not found: Can't resolve 'D:Projecsmy-materials' 巴拉巴拉

仔细分析可以看出,在对应.tmp/view.js里面,路径写的是:

1
2
3
4
import xxx from 'D:\Projects\my-materials\meta.js'
// 这个地方实际应该是:
import xxx from 'D:\\Projects\\my-mterials\\meta.js'
// 由于在JS,单个\是转义符,所以D:\Projects中的\P实际上被转义了。

根据最新的@alifd/build-plugin-lowcode的0.3.0-beta.1,还是有同样的问。如果在windows下,通过path.join拿到路径本身没有问题,例如:

1
path.join('A', 'B') => 'D:\A\B'

这个路径在程序使用上没有问题,但是生成.tmp里面的文件的时候,把路径字符串写入到文件后,文件中的文本实际上是一段转义字符串。所以需要在写入文件的时候,把对应的文本进行\替换为\\
我这边的处理方法是:
对@alifd/build-plugin-lowcode\index.js进行改造,适配windows路径。
具体方案为:

  1. 增加 const os = require(‘os’);
  2. function getEntry(rootDir, entryPath)之前加一个方法normalizePathTextForWindows:
1
2
3
4
5
6
function normalizePathTextForWindows(pathText) {
if (os.platform() === 'win32') {
return pathText.replace(/\\/g, '\\\\');
}
return pathText;
}
  1. 修改getEntry和getScssEntry方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function getEntry(rootDir, entryPath, needNormalizeForWindows) {
if (entryPath && fse.existsSync(path.resolve(rootDir, entryPath))) {
- return path.resolve(rootDir, entryPath)
+ return needNormalizeForWindows ? normalizePathTextForWindows(path.resolve(rootDir, entryPath)) : path.resolve(rootDir, entryPath);
}
for (let i = 0; i < defaultEntryPaths.length; i++) {
const p = path.resolve(rootDir, defaultEntryPaths[i]);
if (fse.existsSync(p)) {
- return p;
+ return needNormalizeForWindows ? normalizePathTextForWindows(p) : p;
}
}
return '';
}

function getScssEntry(rootDir, needNormalizeForWindows) {
for (let i = 0; i < defaultScssEntryPaths.length; i++) {
const p = path.resolve(rootDir, defaultScssEntryPaths[i]);
if (fse.existsSync(p)) {
- return p;
+ return needNormalizeForWindows ? normalizePathTextForWindows(p) : p
}
}
return '';
}
  1. 找到getEntry和getScssEntry调用点:
    getEntry第一个调用点:
1
2
3
4
5
6
7
  INIT_STATE = true;
if (!PARSED_NPM_NAME) {
PARSED_NPM_NAME = parseNpmName(package.name);
}
- const entry = getEntry(rootDir, entryPath);
+ const entry = getEntry(rootDir, entryPath, false);
// 这里要设置为false,因为下面使用entry的地方并不是要用路径字符串,所以不能normalize

getEntry的第二个调用点传true:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    componentViewsExportStr = _componentViews
.map((component) => {
return `const ${component} = getRealComponent(${component}Data, '${component}');\nexport { ${component} };`;
})
.join('\n');
- componentViewsExportStr += `\nexport { default } from '${getEntry(rootDir, entryPath)}';`;
+ componentViewsExportStr += `\nexport { default } from '${getEntry(rootDir, entryPath, true)}';`;
componentViewsImportStr = _componentViews
.map((component) => {
const componentNameFolder = camel2KebabComponentName(component);
const viewJsPath = path.resolve(rootDir, `${lowcodeDir}/${componentNameFolder}/view`);
return `import * as ${component}Data from '${viewJsPath}'`;
})
.join('\n');

getEntry的第三个调用点和getScss的唯一调用点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+  const scssEntry = getScssEntry(rootDir, true);
- const scssEntry = getScssEntry(rootDir);
const viewPath = generateEntry({
template: 'view.js',
filename: 'view.js',
rootDir,
params: {
- entryPath: getEntry(rootDir, entryPath),
+ entryPath: getEntry(rootDir, entryPath, true),
scssImport: scssEntry ? `import '${scssEntry}'` : '',
componentViews,
componentViewsExportStr,
componentViewsImportStr,
library,
execCompile,
},
});

相关讨论在:

windows10 系统下 .tmp 目录内的meta.js 等文件中的路径转义符错误 · Issue #301 · alibaba/lowcode-engine (github.com)

希望阿里可以花点时间修复吧~