Skip to content

Commit 5577b6f

Browse files
committed
feat: support independent subpackage
close #26
1 parent 7437d6a commit 5577b6f

File tree

2 files changed

+140
-30
lines changed

2 files changed

+140
-30
lines changed

template/javascript/build.js

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,34 @@ const terserOptions = {
3333
format: { comments: false },
3434
};
3535

36+
let independentPackages = [];
37+
async function findIndependentPackages() {
38+
const { subpackages } = await fs.readJson(
39+
path.resolve('src', 'app.json'),
40+
'utf8',
41+
);
42+
if (subpackages) {
43+
independentPackages = subpackages
44+
.filter(({ independent }) => independent)
45+
.map(({ root }) => root);
46+
}
47+
}
48+
3649
const builtLibraries = [];
37-
const bundledModules = new Set();
38-
async function bundleModule(module) {
50+
const bundledModules = new Map();
51+
async function bundleModule(module, pkg) {
52+
const bundled = bundledModules.get(pkg);
3953
if (
40-
bundledModules.has(module) ||
54+
bundled?.has(module) ||
4155
builtLibraries.some((library) => module.startsWith(library))
4256
) {
43-
return;
57+
return false;
58+
}
59+
if (bundled) {
60+
bundled.add(module);
61+
} else {
62+
bundledModules.set(pkg, new Set([module]));
4463
}
45-
bundledModules.add(module);
4664

4765
const {
4866
packageJson: { peerDependencies },
@@ -64,12 +82,13 @@ async function bundleModule(module) {
6482
});
6583
await bundle.write({
6684
exports: 'named',
67-
file: `dist/miniprogram_npm/${module}/index.js`,
85+
file: `${pkg.replace('src', 'dist')}/miniprogram_npm/${module}/index.js`,
6886
format: 'cjs',
6987
});
88+
return true;
7089
}
7190

72-
function traverseAST(ast, babelOnly = false) {
91+
function traverseAST(ast, pkg, babelOnly = false) {
7392
traverse.default(ast, {
7493
CallExpression({ node }) {
7594
if (
@@ -81,7 +100,27 @@ function traverseAST(ast, babelOnly = false) {
81100
return;
82101
}
83102

84-
const promise = bundleModule(node.arguments[0].value);
103+
const module = node.arguments[0].value;
104+
let promise = bundleModule(module, pkg);
105+
if (babelOnly) {
106+
promise = promise.then((valid) => {
107+
if (!valid) return;
108+
return Promise.all(
109+
independentPackages.map((item) => {
110+
const bundled = bundledModules.get(item);
111+
if (bundled) {
112+
bundled.add(module);
113+
} else {
114+
bundledModules.set(pkg, new Set([module]));
115+
}
116+
return fs.copy(
117+
path.resolve('dist', 'miniprogram_npm', module),
118+
path.resolve('dist', item, 'miniprogram_npm', module),
119+
);
120+
}),
121+
);
122+
});
123+
}
85124
bundleJobs?.push(promise);
86125
},
87126
});
@@ -118,15 +157,15 @@ async function buildComponentLibrary(name) {
118157
const jobs = [];
119158
const tnm = async (filePath) => {
120159
const result = await babel.transformFileAsync(filePath, { ast: true });
121-
traverseAST(result.ast, true);
160+
traverseAST(result.ast, 'src', true);
122161
const code = __PROD__
123162
? (await minify(result.code, terserOptions)).code
124163
: result.code;
125164
await fs.writeFile(filePath, code);
126165
};
127166

128167
const watcher = chokidar.watch([destination], {
129-
ignored: (path, stats) => stats?.isFile() && !path.endsWith('.js'),
168+
ignored: (file, stats) => stats?.isFile() && !file.endsWith('.js'),
130169
});
131170
watcher.on('add', (filePath) => {
132171
const promise = tnm(filePath);
@@ -136,6 +175,16 @@ async function buildComponentLibrary(name) {
136175
const promise = watcher.close();
137176
jobs.push(promise);
138177
await Promise.all(jobs);
178+
if (independentPackages.length > 0) {
179+
await Promise.all(
180+
independentPackages.map((item) =>
181+
fs.copy(
182+
destination,
183+
path.resolve('dist', item, 'miniprogram_npm', name),
184+
),
185+
),
186+
);
187+
}
139188
resolve();
140189
});
141190
});
@@ -166,7 +215,11 @@ async function processScript(filePath) {
166215
return;
167216
}
168217

169-
traverseAST(ast);
218+
const pkg = independentPackages.find((item) =>
219+
filePath.startsWith(path.normalize(`src/${item}`)),
220+
);
221+
// The `src/` prefix is added to to distinguish `src` and `src/src`.
222+
traverseAST(ast, pkg ? `src/${pkg}` : 'src');
170223

171224
if (__PROD__) {
172225
code = (await minify(code, terserOptions)).code;
@@ -231,12 +284,13 @@ const cb = async (filePath) => {
231284

232285
async function dev() {
233286
await fs.remove('dist');
287+
await findIndependentPackages();
234288
await scanDependencies();
235289
chokidar
236290
.watch(['src'], {
237-
ignored: (path, stats) =>
291+
ignored: (file, stats) =>
238292
stats?.isFile() &&
239-
(path.endsWith('.gitkeep') || path.endsWith('.DS_Store')),
293+
(file.endsWith('.gitkeep') || file.endsWith('.DS_Store')),
240294
})
241295
.on('add', (filePath) => {
242296
const promise = cb(filePath);
@@ -258,11 +312,12 @@ async function dev() {
258312

259313
async function prod() {
260314
await fs.remove('dist');
315+
await findIndependentPackages();
261316
await scanDependencies();
262317
const watcher = chokidar.watch(['src'], {
263-
ignored: (path, stats) =>
318+
ignored: (file, stats) =>
264319
stats?.isFile() &&
265-
(path.endsWith('.gitkeep') || path.endsWith('.DS_Store')),
320+
(file.endsWith('.gitkeep') || file.endsWith('.DS_Store')),
266321
});
267322
watcher.on('add', (filePath) => {
268323
const promise = cb(filePath);

template/typescript/build.js

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,34 @@ const terserOptions = {
3333
format: { comments: false },
3434
};
3535

36+
let independentPackages = [];
37+
async function findIndependentPackages() {
38+
const { subpackages } = await fs.readJson(
39+
path.resolve('src', 'app.json'),
40+
'utf8',
41+
);
42+
if (subpackages) {
43+
independentPackages = subpackages
44+
.filter(({ independent }) => independent)
45+
.map(({ root }) => root);
46+
}
47+
}
48+
3649
const builtLibraries = [];
37-
const bundledModules = new Set();
38-
async function bundleModule(module) {
50+
const bundledModules = new Map();
51+
async function bundleModule(module, pkg) {
52+
const bundled = bundledModules.get(pkg);
3953
if (
40-
bundledModules.has(module) ||
54+
bundled?.has(module) ||
4155
builtLibraries.some((library) => module.startsWith(library))
4256
) {
43-
return;
57+
return false;
58+
}
59+
if (bundled) {
60+
bundled.add(module);
61+
} else {
62+
bundledModules.set(pkg, new Set([module]));
4463
}
45-
bundledModules.add(module);
4664

4765
const {
4866
packageJson: { peerDependencies },
@@ -64,12 +82,13 @@ async function bundleModule(module) {
6482
});
6583
await bundle.write({
6684
exports: 'named',
67-
file: `dist/miniprogram_npm/${module}/index.js`,
85+
file: `${pkg.replace('src', 'dist')}/miniprogram_npm/${module}/index.js`,
6886
format: 'cjs',
6987
});
88+
return true;
7089
}
7190

72-
function traverseAST(ast, babelOnly = false) {
91+
function traverseAST(ast, pkg, babelOnly = false) {
7392
traverse.default(ast, {
7493
CallExpression({ node }) {
7594
if (
@@ -81,7 +100,27 @@ function traverseAST(ast, babelOnly = false) {
81100
return;
82101
}
83102

84-
const promise = bundleModule(node.arguments[0].value);
103+
const module = node.arguments[0].value;
104+
let promise = bundleModule(module, pkg);
105+
if (babelOnly) {
106+
promise = promise.then((valid) => {
107+
if (!valid) return;
108+
return Promise.all(
109+
independentPackages.map((item) => {
110+
const bundled = bundledModules.get(item);
111+
if (bundled) {
112+
bundled.add(module);
113+
} else {
114+
bundledModules.set(pkg, new Set([module]));
115+
}
116+
return fs.copy(
117+
path.resolve('dist', 'miniprogram_npm', module),
118+
path.resolve('dist', item, 'miniprogram_npm', module),
119+
);
120+
}),
121+
);
122+
});
123+
}
85124
bundleJobs?.push(promise);
86125
},
87126
});
@@ -118,15 +157,15 @@ async function buildComponentLibrary(name) {
118157
const jobs = [];
119158
const tnm = async (filePath) => {
120159
const result = await babel.transformFileAsync(filePath, { ast: true });
121-
traverseAST(result.ast, true);
160+
traverseAST(result.ast, 'src', true);
122161
const code = __PROD__
123162
? (await minify(result.code, terserOptions)).code
124163
: result.code;
125164
await fs.writeFile(filePath, code);
126165
};
127166

128167
const watcher = chokidar.watch([destination], {
129-
ignored: (path, stats) => stats?.isFile() && !path.endsWith('.js'),
168+
ignored: (file, stats) => stats?.isFile() && !file.endsWith('.js'),
130169
});
131170
watcher.on('add', (filePath) => {
132171
const promise = tnm(filePath);
@@ -136,6 +175,16 @@ async function buildComponentLibrary(name) {
136175
const promise = watcher.close();
137176
jobs.push(promise);
138177
await Promise.all(jobs);
178+
if (independentPackages.length > 0) {
179+
await Promise.all(
180+
independentPackages.map((item) =>
181+
fs.copy(
182+
destination,
183+
path.resolve('dist', item, 'miniprogram_npm', name),
184+
),
185+
),
186+
);
187+
}
139188
resolve();
140189
});
141190
});
@@ -166,7 +215,11 @@ async function processScript(filePath) {
166215
return;
167216
}
168217

169-
traverseAST(ast);
218+
const pkg = independentPackages.find((item) =>
219+
filePath.startsWith(path.normalize(`src/${item}`)),
220+
);
221+
// The `src/` prefix is added to to distinguish `src` and `src/src`.
222+
traverseAST(ast, pkg ? `src/${pkg}` : 'src');
170223

171224
if (__PROD__) {
172225
code = (await minify(code, terserOptions)).code;
@@ -231,12 +284,13 @@ const cb = async (filePath) => {
231284

232285
async function dev() {
233286
await fs.remove('dist');
287+
await findIndependentPackages();
234288
await scanDependencies();
235289
chokidar
236290
.watch(['src'], {
237-
ignored: (path, stats) =>
291+
ignored: (file, stats) =>
238292
stats?.isFile() &&
239-
(path.endsWith('.gitkeep') || path.endsWith('.DS_Store')),
293+
(file.endsWith('.gitkeep') || file.endsWith('.DS_Store')),
240294
})
241295
.on('add', (filePath) => {
242296
const promise = cb(filePath);
@@ -258,11 +312,12 @@ async function dev() {
258312

259313
async function prod() {
260314
await fs.remove('dist');
315+
await findIndependentPackages();
261316
await scanDependencies();
262317
const watcher = chokidar.watch(['src'], {
263-
ignored: (path, stats) =>
318+
ignored: (file, stats) =>
264319
stats?.isFile() &&
265-
(path.endsWith('.gitkeep') || path.endsWith('.DS_Store')),
320+
(file.endsWith('.gitkeep') || file.endsWith('.DS_Store')),
266321
});
267322
watcher.on('add', (filePath) => {
268323
const promise = cb(filePath);

0 commit comments

Comments
 (0)