mirror of
https://github.com/motajs/template.git
synced 2026-11-10 13:04:30 +08:00
refactor: 构建脚本
This commit is contained in:
1 parent
d35f8303da
commit
3cc97e5ed3
8 files changed
+672
-833
No files matched your search
@@ -0,0 +1,144 @@
|
||||
import { build } from 'vite';
|
||||
import { RollupOutput } from 'rollup';
|
||||
import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { dataIsolationPlugin } from './build-plugin';
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
/** 创建独立的临时构建根目录,并登记以便用例结束后统一清理 */
|
||||
async function createRoot() {
|
||||
const root = await mkdtemp(join(tmpdir(), 'mota-data-isolation-'));
|
||||
tempDirs.push(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
/** 在临时根目录下写入文件,必要时创建父目录,返回写入后的绝对路径 */
|
||||
async function writeRootFile(root: string, name: string, content: string) {
|
||||
const file = join(root, name);
|
||||
await mkdir(dirname(file), { recursive: true });
|
||||
await writeFile(file, content, 'utf8');
|
||||
return file;
|
||||
}
|
||||
|
||||
/** 以数据端库模式 ESM 配置执行一次真实的 vite 构建 */
|
||||
function buildFixture(root: string, entry: string) {
|
||||
return build({
|
||||
configFile: false,
|
||||
root,
|
||||
logLevel: 'silent',
|
||||
build: {
|
||||
write: false,
|
||||
minify: false,
|
||||
copyPublicDir: false,
|
||||
lib: {
|
||||
entry,
|
||||
formats: ['es'],
|
||||
fileName: 'data'
|
||||
}
|
||||
},
|
||||
plugins: [dataIsolationPlugin()]
|
||||
});
|
||||
}
|
||||
|
||||
/** 执行构建并返回错误信息,构建成功时返回空字符串 */
|
||||
async function getBuildError(root: string, entry: string) {
|
||||
try {
|
||||
await buildFixture(root, entry);
|
||||
} catch (e) {
|
||||
return String(e);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
const dirs = tempDirs.splice(0);
|
||||
await Promise.all(
|
||||
dirs.map(dir => rm(dir, { recursive: true, force: true }))
|
||||
);
|
||||
});
|
||||
|
||||
describe('dataIsolationPlugin', () => {
|
||||
// 直接引入 vue 说明符的数据端模块必须被插件拒绝
|
||||
it('rejects a render-side specifier', async () => {
|
||||
const root = await createRoot();
|
||||
const entry = await writeRootFile(root, 'entry.ts', "import 'vue';\n");
|
||||
|
||||
const message = await getBuildError(root, entry);
|
||||
|
||||
expect(message).toContain('[mota-data-isolation]');
|
||||
expect(message).toContain('matched: vue');
|
||||
expect(message).toContain(
|
||||
'data-side build must not depend on render-side'
|
||||
);
|
||||
});
|
||||
|
||||
// 相对引入的 src/client 渲染目录必须按解析路径被 moduleParsed 拒绝
|
||||
it('rejects a resolved src/client module', async () => {
|
||||
const root = await createRoot();
|
||||
await writeRootFile(
|
||||
root,
|
||||
'src/client/ui/fake.ts',
|
||||
'export const fake = 1;\n'
|
||||
);
|
||||
const entry = await writeRootFile(
|
||||
root,
|
||||
'entry.ts',
|
||||
"import './src/client/ui/fake';\n"
|
||||
);
|
||||
|
||||
const message = await getBuildError(root, entry);
|
||||
|
||||
expect(message).toContain('[mota-data-isolation]');
|
||||
expect(message).toContain('matched: src/client');
|
||||
});
|
||||
|
||||
// 相对引入的 packages-user/client-* 必须按解析路径被 moduleParsed 拒绝
|
||||
it('rejects a resolved packages-user client package', async () => {
|
||||
const root = await createRoot();
|
||||
await writeRootFile(
|
||||
root,
|
||||
'packages-user/client-modules/fake.ts',
|
||||
'export const fake = 1;\n'
|
||||
);
|
||||
const entry = await writeRootFile(
|
||||
root,
|
||||
'entry.ts',
|
||||
"import './packages-user/client-modules/fake';\n"
|
||||
);
|
||||
|
||||
const message = await getBuildError(root, entry);
|
||||
|
||||
expect(message).toContain('[mota-data-isolation]');
|
||||
expect(message).toContain('matched: packages-user/client-');
|
||||
});
|
||||
|
||||
// 纯数据端依赖必须通过构建并产出 ESM 代码
|
||||
it('passes a pure data-side graph and emits ESM', async () => {
|
||||
const root = await createRoot();
|
||||
await writeRootFile(
|
||||
root,
|
||||
'packages-user/data-common/fake.ts',
|
||||
'export const value = 1;\n'
|
||||
);
|
||||
const entry = await writeRootFile(
|
||||
root,
|
||||
'entry.ts',
|
||||
"export { value } from './packages-user/data-common/fake';\n"
|
||||
);
|
||||
|
||||
const result = (await buildFixture(root, entry)) as
|
||||
| RollupOutput
|
||||
| RollupOutput[];
|
||||
const outputs = Array.isArray(result) ? result : [result];
|
||||
const code = outputs
|
||||
.flatMap(v => v.output)
|
||||
.filter(v => v.type === 'chunk')
|
||||
.map(v => v.code)
|
||||
.join('\n');
|
||||
|
||||
expect(code).toContain('export');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user