Skip to content

Commit 965fb95

Browse files
committed
Modernize and simplify our packages building tools, replace Rollup by tsup
1 parent 61d79b6 commit 965fb95

File tree

102 files changed

+6464
-6381
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+6464
-6381
lines changed

bin/build_package.ts

Lines changed: 93 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
import * as fs from 'node:fs';
66
import * as path from 'node:path';
77
import { parseArgs } from 'node:util';
8-
import * as LightningCSS from 'lightningcss';
9-
import * as rollup from 'rollup';
108
import { globSync } from 'tinyglobby';
11-
import { getRollupConfiguration } from './rollup.ts';
9+
import { build } from 'tsup';
10+
import { readPackageJSON } from "pkg-types";
1211

1312
const args = parseArgs({
1413
allowPositionals: true,
@@ -34,117 +33,105 @@ async function main() {
3433
process.exit(1);
3534
}
3635

37-
const packageData = await import(path.join(packageRoot, 'package.json'), {with: { type: 'json'}});
38-
const packageName = packageData.name;
39-
const srcDir = path.join(packageRoot, 'src');
40-
const distDir = path.join(packageRoot, 'dist');
36+
const packageData = await readPackageJSON(path.join(packageRoot, 'package.json'));
37+
const isStimulusBundle = '@symfony/stimulus-bundle' === packageData.name;
38+
const isReactOrVueOrSvelte = ['@symfony/ux-react', '@symfony/ux-vue', '@symfony/ux-svelte'].some(name => packageData.name.startsWith(name));
4139

42-
if (!fs.existsSync(srcDir)) {
43-
console.error(`The package directory "${packageRoot}" does not contain a "src" directory.`);
44-
process.exit(1);
45-
}
46-
47-
if (fs.existsSync(distDir)) {
48-
console.log(`Cleaning up the "${distDir}" directory...`);
49-
await fs.promises.rm(distDir, { recursive: true });
50-
await fs.promises.mkdir(distDir);
51-
}
52-
53-
const inputScriptFiles = [
54-
...globSync(path.join(srcDir, '*controller.ts')),
55-
...(['@symfony/ux-react', '@symfony/ux-vue', '@symfony/ux-svelte'].includes(packageName)
56-
? [path.join(srcDir, 'loader.ts'), path.join(srcDir, 'components.ts')]
57-
: []),
58-
...(packageName === '@symfony/stimulus-bundle'
59-
? [path.join(srcDir, 'loader.ts'), path.join(srcDir, 'controllers.ts')]
60-
: []),
40+
const inputCssFile = packageData?.config?.css_source;
41+
const inputFiles = [
42+
...globSync('src/*controller.ts'),
43+
...(isStimulusBundle ? ['src/loader.ts', 'src/controllers.ts'] : []),
44+
...(isReactOrVueOrSvelte ? ['src/loader.ts', 'src/components.ts'] : []),
45+
...(inputCssFile ? [inputCssFile] : []),
6146
];
6247

63-
const inputStyleFile = packageData.config?.css_source;
64-
const buildCss = async () => {
65-
if (!inputStyleFile) {
66-
return;
48+
const external = new Set([
49+
// We force "dependencies" and "peerDependencies" to be external to avoid bundling them.
50+
...Object.keys(packageData.dependencies || {}),
51+
...Object.keys(packageData.peerDependencies || {}),
52+
]);
53+
54+
inputFiles.forEach((file) => {
55+
// custom handling for StimulusBundle
56+
if (file.includes('StimulusBundle/assets/src/loader.ts')) {
57+
external.add('./controllers.js');
6758
}
68-
const inputStyleFileDist = path.resolve(distDir, `${path.basename(inputStyleFile, '.css')}.min.css`);
69-
70-
console.log('Minifying CSS...');
71-
const css = await fs.promises.readFile(inputStyleFile, 'utf-8');
72-
const { code: minified } = LightningCSS.transform({
73-
filename: path.basename(inputStyleFile, '.css'),
74-
code: Buffer.from(css),
75-
minify: true,
76-
sourceMap: false, // TODO: Maybe we can add source maps later? :)
77-
});
78-
await fs.promises.writeFile(inputStyleFileDist, minified);
79-
};
80-
81-
if (inputScriptFiles.length === 0) {
82-
console.error(
83-
`No input files found for package "${packageName}" (directory "${packageRoot}").\nEnsure you have at least a file matching the pattern "src/*_controller.ts", or manually specify input files in "${import.meta.filename}" file.`
84-
);
85-
process.exit(1);
86-
}
8759

88-
const rollupConfig = getRollupConfiguration({
89-
packageRoot,
90-
inputFiles: inputScriptFiles,
91-
isWatch,
92-
additionalPlugins: [
93-
...(isWatch && inputStyleFile
94-
? [
95-
{
96-
name: 'watcher',
97-
buildStart(this: rollup.PluginContext) {
98-
this.addWatchFile(inputStyleFile);
99-
},
100-
},
101-
]
102-
: []),
103-
],
60+
// React, Vue, Svelte
61+
if (file.includes('assets/src/loader.ts')) {
62+
external.add('./components.js');
63+
}
10464
});
10565

106-
if (isWatch) {
107-
console.log(
108-
`Watching for JavaScript${inputStyleFile ? ' and CSS' : ''} files modifications in "${srcDir}" directory...`
109-
);
110-
111-
const watcher = rollup.watch(rollupConfig);
112-
watcher.on('event', (event) => {
113-
if (event.code === 'ERROR') {
114-
console.error('Error during build:', event.error);
115-
}
116-
117-
if ((event.code === 'BUNDLE_END' || event.code === 'ERROR') && event.result) {
118-
event.result.close();
119-
}
120-
});
121-
watcher.on('change', async (id, { event }) => {
122-
if (event === 'update') {
123-
console.log('Files were modified, rebuilding...');
124-
}
125-
126-
if (inputStyleFile && id === inputStyleFile) {
127-
await buildCss();
66+
await build({
67+
entry: inputFiles,
68+
outDir: path.join(packageRoot, 'dist'),
69+
clean: true,
70+
external: Array.from(external),
71+
format: 'esm',
72+
platform: 'browser',
73+
tsconfig: path.join(import.meta.dirname, '../tsconfig.packages.json'),
74+
dts: {
75+
entry: inputFiles.filter(inputFile => !inputFile.endsWith('.css')),
76+
},
77+
watch: isWatch,
78+
splitting: false,
79+
esbuildOptions(options) {
80+
// Disabling `bundle` option prevent esbuild to inline relative (but external) imports (like "./components.js" for React, Vue, Svelte).
81+
options.bundle = !(isStimulusBundle || isReactOrVueOrSvelte);
82+
},
83+
plugins: [
84+
{
85+
/**
86+
* This plugin is used to minify CSS files using LightningCSS.
87+
*
88+
* Even if tsup supports CSS minification through ESBuild by setting the `minify: true` option,
89+
* it also minifies JS files but we don't want that.
90+
*/
91+
name: 'symfony-ux:minify-css',
92+
async renderChunk(code, chunkInfo) {
93+
if (!/\.css$/.test(chunkInfo.path)) {
94+
return null;
95+
}
96+
97+
const { transform } = await import('lightningcss');
98+
const result = transform({
99+
filename: chunkInfo.path,
100+
code: Buffer.from(code),
101+
minify: true,
102+
});
103+
104+
console.log(`[Symfony UX] Minified CSS file: ${chunkInfo.path}`);
105+
106+
return {
107+
code: result.code.toString(),
108+
map: result.map ? result.map.toString() : null,
109+
}
110+
},
111+
},
112+
113+
/**
114+
* Unlike tsdown/rolldown and the option "cssEntryFileNames", tsup does not support
115+
* customizing the output file names for CSS files.
116+
* A plugin is needed to rename the written CSS files to add the ".min" suffix.
117+
*/
118+
{
119+
name: 'symfony-ux:append-min-to-css',
120+
async buildEnd({ writtenFiles }) {
121+
for (const writtenFile of writtenFiles) {
122+
if (!writtenFile.name.endsWith('.css')) {
123+
continue;
124+
}
125+
126+
const newName = writtenFile.name.replace(/\.css$/, '.min.css');
127+
await fs.promises.rename(writtenFile.name, newName);
128+
129+
console.info(`[Symfony UX] Renamed ${writtenFile.name} to ${newName}`);
130+
}
131+
}
128132
}
129-
});
130-
} else {
131-
console.log(`Building JavaScript files from ${packageName} package...`);
132-
const start = Date.now();
133-
134-
if (typeof rollupConfig.output === 'undefined' || Array.isArray(rollupConfig.output)) {
135-
console.error(
136-
`The rollup configuration for package "${packageName}" does not contain a valid output configuration.`
137-
);
138-
process.exit(1);
139-
}
140-
141-
const bundle = await rollup.rollup(rollupConfig);
142-
await bundle.write(rollupConfig.output);
143-
144-
await buildCss();
145-
146-
console.log(`Done in ${((Date.now() - start) / 1000).toFixed(3)} seconds.`);
147-
}
133+
],
134+
});
148135
}
149136

150137
main();

package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@
1414
},
1515
"devDependencies": {
1616
"@biomejs/biome": "^2.0.4",
17-
"@rollup/plugin-commonjs": "^28.0.6",
18-
"@rollup/plugin-node-resolve": "^16.0.1",
19-
"@rollup/plugin-typescript": "^12.1.4",
2017
"@testing-library/dom": "catalog:",
2118
"@testing-library/jest-dom": "catalog:",
2219
"@types/node": "^22.6.0",
2320
"lightningcss": "^1.28.2",
21+
"pkg-types": "^2.2.0",
2422
"playwright": "^1.47.0",
25-
"rollup": "^4.44.1",
2623
"tinyglobby": "^0.2.14",
24+
"tsup": "^8.5.0",
2725
"vitest": "catalog:"
2826
},
2927
"version": "2.27.0"

0 commit comments

Comments
 (0)