From 6f990276bee45e83ae3a28277e6d802c654d54fb Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 3 Apr 2024 16:07:29 +1000 Subject: [PATCH 01/17] feat: add vite as default bundler, use vitest with vite --- .github/workflows/e2e-linux.yml | 2 + .github/workflows/e2e-macOS.yml | 2 + .github/workflows/e2e-windows.yml | 2 + .../my-app.spec.ext | 5 +- before.js | 4 +- common/package.json | 1 + questions.js | 10 ++-- vite/index.html | 22 +++++++ vite/package.json | 31 ++++++++++ vite/tsconfig.vitest.json__if_vitest | 8 +++ vite/vite.config.ext | 58 +++++++++++++++++++ vite/vitest.config.ext__if_vitest | 17 ++++++ webpack/package.json | 3 - webpack/webpack.config.js | 54 +---------------- 14 files changed, 157 insertions(+), 62 deletions(-) create mode 100644 vite/index.html create mode 100644 vite/package.json create mode 100644 vite/tsconfig.vitest.json__if_vitest create mode 100644 vite/vite.config.ext create mode 100644 vite/vitest.config.ext__if_vitest diff --git a/.github/workflows/e2e-linux.yml b/.github/workflows/e2e-linux.yml index 3f9770c..f2e6494 100644 --- a/.github/workflows/e2e-linux.yml +++ b/.github/workflows/e2e-linux.yml @@ -29,6 +29,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript + - latest,vite,babel + - latest,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} diff --git a/.github/workflows/e2e-macOS.yml b/.github/workflows/e2e-macOS.yml index c145068..02a67c0 100644 --- a/.github/workflows/e2e-macOS.yml +++ b/.github/workflows/e2e-macOS.yml @@ -26,6 +26,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript + - latest,vite,babel + - latest,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} diff --git a/.github/workflows/e2e-windows.yml b/.github/workflows/e2e-windows.yml index c784b7c..c5dfce4 100644 --- a/.github/workflows/e2e-windows.yml +++ b/.github/workflows/e2e-windows.yml @@ -26,6 +26,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript + - latest,vite,babel + - latest,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} diff --git a/app-min/test__if_not_no-unit-tests/my-app.spec.ext b/app-min/test__if_not_no-unit-tests/my-app.spec.ext index 60350f5..bc8ccfc 100644 --- a/app-min/test__if_not_no-unit-tests/my-app.spec.ext +++ b/app-min/test__if_not_no-unit-tests/my-app.spec.ext @@ -1,6 +1,9 @@ // @if mocha import { expect } from 'chai'; // @endif +// @if vitest +import { describe, it, expect } from 'vitest'; +// @endif // @if shadow-dom import { CustomElement } from 'aurelia'; // @endif @@ -25,7 +28,7 @@ describe('my-app', () => { // @if !shadow-dom const text = node.textContent; // @endif - // @if jasmine || jest + // @if jasmine || jest || vitest expect(text.trim()).toBe('Hello World!'); // @endif // @if mocha diff --git a/before.js b/before.js index 0abeb26..a4a97dd 100644 --- a/before.js +++ b/before.js @@ -1,8 +1,8 @@ // Use "before" task to ask user to select a preset (to skip questionnaire). const PRESETS = { - 'default-esnext': ['app', 'webpack', 'babel', 'jest'], - 'default-typescript': ['app', 'webpack', 'typescript', 'jest'], + 'default-esnext': ['app', 'vite', 'babel', 'jest'], + 'default-typescript': ['app', 'vite', 'typescript', 'jest'], 'default-esnext-plugin': ['plugin', 'webpack', 'babel', 'shadow-dom', 'jest'], 'default-typescript-plugin': ['plugin', 'webpack', 'typescript', 'shadow-dom', 'jest'], }; diff --git a/common/package.json b/common/package.json index 7e3dca7..fcbfbb6 100644 --- a/common/package.json +++ b/common/package.json @@ -5,6 +5,7 @@ // @endif // @if plugin "description": "An Aurelia 2 plugin.", + "type": "module", "main": "dist/index.js", "files": [ "dist" diff --git a/questions.js b/questions.js index a26882e..3641fcd 100644 --- a/questions.js +++ b/questions.js @@ -16,7 +16,8 @@ module.exports = [ { message: 'Which bundler would you like to use?', choices: [ - {value: 'webpack', title: 'Webpack', hint: 'A powerful and popular bundler for modern JavaScript apps.'}, + {value: 'vite', title: 'Vite', hint: 'Next Generation Frontend Tooling.'}, + {if: 'app', value: 'webpack', title: 'Webpack', hint: 'A powerful and popular bundler for modern JavaScript apps.'}, {if: 'app', value: 'dumber', title: 'Dumber', hint: 'A dumb JavasScript bundler, dumber than you and me. The successor of Aurelia CLI built-in bundler.'}, {if: 'app', value: 'parcel', title: 'Parcel', hint: 'Blazing fast, zero configuration web application bundler.'}, ] @@ -49,9 +50,10 @@ module.exports = [ message: 'What unit testing framework to use?', choices: [ {value: 'no-unit-tests', title: 'None', hint: 'No unit testing'}, - {value: 'jest', title: 'Jest', hint: 'Runs in Node.js, simulates browser by default, with a focus on simplicity.'}, - {value: 'jasmine', title: 'Jasmine', hint: 'Runs in browser, a behavior-driven testing framework.'}, - {value: 'mocha', title: 'Mocha + Chai', hint: 'Runs in browser, a feature-rich JavaScript test framework for node and browsers.'} + {if: '!vite', value: 'jest', title: 'Jest', hint: 'Runs in Node.js, simulates browser by default, with a focus on simplicity.'}, + {if: '!vite', value: 'jasmine', title: 'Jasmine', hint: 'Runs in browser, a behavior-driven testing framework.'}, + {if: '!vite', value: 'mocha', title: 'Mocha + Chai', hint: 'Runs in browser, a feature-rich JavaScript test framework for node and browsers.'}, + {if: 'vite', value: 'vitest', title:'Vitest', hint: 'A Vite-native testing framework.'} ] }, { diff --git a/vite/index.html b/vite/index.html new file mode 100644 index 0000000..002212d --- /dev/null +++ b/vite/index.html @@ -0,0 +1,22 @@ + + + + + + Aurelia + + + + + + + + + + + + + + + + diff --git a/vite/package.json b/vite/package.json new file mode 100644 index 0000000..2842ede --- /dev/null +++ b/vite/package.json @@ -0,0 +1,31 @@ +{ + "type": "module", + "devDependencies": { + "@aurelia/vite-plugin": /* @if latest */"latest"/* @endif *//* @if dev */"dev"/* @endif */, + "vite": "^5.1.4", + "vite-plugin-node-polyfills": "^0.21.0", + // @if babel + "vite-plugin-babel": "^1.2.0", + // @endif + // @if typescript && plugin + "vite-plugin-dts": "^3.8.1", + // @endif + // @if vitest + "vitest": "^1.4.0", + "jsdom": "^24.0.0", + // @endif + // @if less + "less": "^4.2.0", + // @endif + // @if sass + "sass": "^1.72.0", + // @endif + }, + "scripts": { + "start": "vite", + "build": "vite build", + // @if vitest + "test": "vitest", + // @endif + } +} diff --git a/vite/tsconfig.vitest.json__if_vitest b/vite/tsconfig.vitest.json__if_vitest new file mode 100644 index 0000000..e0a57fe --- /dev/null +++ b/vite/tsconfig.vitest.json__if_vitest @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + "types": ["node", "jsdom"] + } +} \ No newline at end of file diff --git a/vite/vite.config.ext b/vite/vite.config.ext new file mode 100644 index 0000000..a02923b --- /dev/null +++ b/vite/vite.config.ext @@ -0,0 +1,58 @@ +import { defineConfig } from 'vite'; +import { nodePolyfills } from 'vite-plugin-node-polyfills' +import aurelia from '@aurelia/vite-plugin'; +// @if babel +import babel from 'vite-plugin-babel'; +// @endif +// @if plugin +import { resolve } from 'path'; +// @if typescript +import dts from 'vite-plugin-dts'; +// @endif +// @endif + +export default defineConfig({ + server: { + open: !process.env.CI, + port: 9000, + }, + // @if plugin + build: { + lib: { + entry: resolve(__dirname, 'src/index./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */'), + // Generate ESM dist file only. + formats: ['es'], + fileName: 'index', + }, + rollupOptions: { + // Add all 3rd party dependencies here to avoid bundling. + external: [/@aurelia\/\w+/, 'aurelia'], + }, + }, + // @endif + plugins: [ + aurelia({ + useDev: true, + // @if plugin + include: '{src,dev-app}/**/*.{ts,js,html}', + // @endif + // @if shadow-dom + // The other possible Shadow DOM mode is 'closed'. + // If you turn on "closed" mode, there will be difficulty to perform e2e + // tests (such as Playwright). Because shadowRoot is not accessible through + // standard DOM APIs in "closed" mode. + defaultShadowOptions: { mode: 'open' }, + // @endif + // @if css-module + useCSSModule: true, + // @endif + }), + // @if babel + babel(), + // @endif + nodePolyfills(), + // @if typescript && plugin + dts(), + // @endif + ], +}); diff --git a/vite/vitest.config.ext__if_vitest b/vite/vitest.config.ext__if_vitest new file mode 100644 index 0000000..1261649 --- /dev/null +++ b/vite/vitest.config.ext__if_vitest @@ -0,0 +1,17 @@ +import { fileURLToPath } from "node:url"; +import { mergeConfig, defineConfig/* @if playwright */, configDefaults/* @endif */ } from "vitest/config"; +import viteConfig from "./vite.config"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: "jsdom", + watch: false, + // @if playwright + exclude: [...configDefaults.exclude, "e2e/*"], + // @endif + root: fileURLToPath(new URL("./", import.meta.url)), + }, + }), +); \ No newline at end of file diff --git a/webpack/package.json b/webpack/package.json index bd76e89..70f8b76 100644 --- a/webpack/package.json +++ b/webpack/package.json @@ -29,9 +29,6 @@ // @if jasmine || mocha "webpack-shell-plugin-next": "^2.3.1", // @endif - // @if plugin - "webpack-node-externals": "^3.0.0", - // @endif }, "scripts": { "start": "webpack serve", diff --git a/webpack/webpack.config.js b/webpack/webpack.config.js index 216027f..c9033af 100644 --- a/webpack/webpack.config.js +++ b/webpack/webpack.config.js @@ -9,9 +9,6 @@ const TerserPlugin = require('terser-webpack-plugin'); // @if jasmine || mocha const WebpackShellPluginNext = require('webpack-shell-plugin-next') // @endif -// @if plugin -const nodeExternals = require('webpack-node-externals'); -// @endif // @if !css-module const cssLoader = 'css-loader'; @@ -53,12 +50,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a const test = env.test || process.env.NODE_ENV === 'test'; // @endif return { - // @if app target: 'web', - // @endif - // @if plugin - target: production ? 'node' : 'web', - // @endif mode: production ? 'production' : 'development', devtool: production ? undefined : 'eval-source-map', optimization: { @@ -78,42 +70,22 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a entry: { entry: test ? './test/all-spec./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' : - // @if app './src/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' - // @endif - // @if plugin - // Build only plugin in production mode, - // build dev-app in non-production mode - (production ? './src/index./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' : './dev-app/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */') - // @endif }, // @endif // @if !jasmine && !mocha entry: { - // @if app entry: './src/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' - // @endif - // @if plugin - // Build only plugin in production mode, - // build dev-app in non-production mode - entry: production? './src/index./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' : './dev-app/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' - // @endif }, // @endif output: { clean: true, path: path.resolve(__dirname, 'dist'), - // @if app filename: production ? '[name].[contenthash].bundle.js' : '[name].bundle.js' - // @endif - // @if plugin - filename: production ? 'index.js' : '[name].bundle.js', - library: production ? { type: 'commonjs' } : undefined - // @endif }, resolve: { extensions: [/* @if typescript */'.ts', /* @endif */'.js'], - modules: [path.resolve(__dirname, 'src'),/* @if !production */ path.resolve(__dirname, 'dev-app'),/* @endif */ 'node_modules'], + modules: [path.resolve(__dirname, 'src'), 'node_modules'], alias: production ? { // add your production aliases here } : { @@ -221,12 +193,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // @endif // @if shadow-dom { - // @if app test: /[/\\]src[/\\].+\.html$/i, - // @endif - // @if plugin - test: /[/\\](?:src|dev-app)[/\\].+\.html$/i, - // @endif use: { loader: '@aurelia/webpack-loader', options: { @@ -242,12 +209,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // @endif // @if css-module { - // @if app test: /[/\\]src[/\\].+\.html$/i, - // @endif - // @if plugin - test: /[/\\](?:src|dev-app)[/\\].+\.html$/i, - // @endif use: { loader: '@aurelia/webpack-loader', options: { useCSSModule: true } @@ -257,27 +219,15 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // @endif // @if !shadow-dom && !css-module { - // @if app test: /[/\\]src[/\\].+\.html$/i, - // @endif - // @if plugin - test: /[/\\](?:src|dev-app)[/\\].+\.html$/i, - // @endif use: '@aurelia/webpack-loader', exclude: /node_modules/ } // @endif ] }, - // @if plugin - externalsPresets: { node: production }, - externals: [ - // Skip npm dependencies in plugin build. - production && nodeExternals() - ].filter(p => p), - // @endif plugins: [ - /* @if plugin */!production && /* @endif */new HtmlWebpackPlugin({ template: 'index.html', favicon: 'favicon.ico' }), + new HtmlWebpackPlugin({ template: 'index.html', favicon: 'favicon.ico' }), new Dotenv({ path: `./.env${production ? '' : '.' + (process.env.NODE_ENV || 'development')}`, }), From 03e9b6a84c26e4a45fdfb3a71439202e41e42052 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 29 May 2024 15:08:24 +1000 Subject: [PATCH 02/17] feat(all): normalise all css-module setup to use .module.css convention --- __test__/before-task.spec.js | 8 ++-- __test__/transforms.spec.js | 64 +++++++++++++++++++++++++ before.js | 4 +- common/src/resource.d.ts__if_typescript | 6 +-- dumber/gulpfile.js | 8 ++-- jest/package.json | 10 +--- parcel/README.md | 2 +- parcel/package.json | 9 +--- questions.js | 2 +- transforms.js | 4 ++ vite/vite.config.ext | 3 -- webpack/webpack.config.js | 60 +++++++---------------- 12 files changed, 101 insertions(+), 79 deletions(-) diff --git a/__test__/before-task.spec.js b/__test__/before-task.spec.js index d5af5f0..7b19463 100644 --- a/__test__/before-task.spec.js +++ b/__test__/before-task.spec.js @@ -23,7 +23,7 @@ test('"before" task can select default-esnext preset', async t => { const result = await before({unattended: false, prompts}); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['app', 'webpack', 'babel', 'jest'] + preselectedFeatures: ['app', 'vite', 'babel', 'jest'] }); }); @@ -40,7 +40,7 @@ test('"before" task can select default-typescript preset', async t => { const result = await before({unattended: false, prompts}); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['app', 'webpack', 'typescript', 'jest'] + preselectedFeatures: ['app', 'vite', 'typescript', 'jest'] }); }); @@ -55,7 +55,7 @@ test('"before" task can select default-esnext-plugin preset', async t => { const result = await before({ unattended: false, prompts }); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['plugin', 'webpack', 'babel', 'shadow-dom', 'jest'] + preselectedFeatures: ['plugin', 'vite', 'babel', 'shadow-dom', 'jest'] }); }); @@ -72,7 +72,7 @@ test('"before" task can select default-typescript-plugin preset', async t => { const result = await before({ unattended: false, prompts }); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['plugin', 'webpack', 'typescript', 'shadow-dom', 'jest'] + preselectedFeatures: ['plugin', 'vite', 'typescript', 'shadow-dom', 'jest'] }); }); test('"before" task can select no preset', async t => { diff --git a/__test__/transforms.spec.js b/__test__/transforms.spec.js index f14f863..e03af2f 100644 --- a/__test__/transforms.spec.js +++ b/__test__/transforms.spec.js @@ -71,3 +71,67 @@ test.cb('ext-transform translates .ext file to .ts file when typescript is selec contents: Buffer.from('

') })); }); + +test.cb('ext-transform translates css files to .module.css files when css-module is selected', t => { + const jsExt = extTransform({}, ['css-module']); + const files = []; + + jsExt.pipe(new Writable({ + objectMode: true, + write(file, enc, cb) { + files.push(file); + cb(); + } + })); + + jsExt.on('end', () => { + t.is(files.length, 2); + t.is(files[0].path.replace(/\\/g, '/'), 'test/a.module.css'); + t.is(files[0].contents.toString(), '.p { color: green; }'); + t.is(files[1].path.replace(/\\/g, '/'), 'test/b.module.scss'); + t.is(files[1].contents.toString(), '.p { color: red; }'); + t.end(); + }) + + jsExt.write(new Vinyl({ + path: 'test/a.css', + contents: Buffer.from('.p { color: green; }') + })); + + jsExt.end(new Vinyl({ + path: 'test/b.scss', + contents: Buffer.from('.p { color: red; }') + })); +}); + +test.cb('ext-transform leaves css files untouched files when css-module is not selected', t => { + const jsExt = extTransform({}, ['']); + const files = []; + + jsExt.pipe(new Writable({ + objectMode: true, + write(file, enc, cb) { + files.push(file); + cb(); + } + })); + + jsExt.on('end', () => { + t.is(files.length, 2); + t.is(files[0].path.replace(/\\/g, '/'), 'test/a.css'); + t.is(files[0].contents.toString(), '.p { color: green; }'); + t.is(files[1].path.replace(/\\/g, '/'), 'test/b.scss'); + t.is(files[1].contents.toString(), '.p { color: red; }'); + t.end(); + }) + + jsExt.write(new Vinyl({ + path: 'test/a.css', + contents: Buffer.from('.p { color: green; }') + })); + + jsExt.end(new Vinyl({ + path: 'test/b.scss', + contents: Buffer.from('.p { color: red; }') + })); +}); \ No newline at end of file diff --git a/before.js b/before.js index a4a97dd..6a9a43d 100644 --- a/before.js +++ b/before.js @@ -3,8 +3,8 @@ const PRESETS = { 'default-esnext': ['app', 'vite', 'babel', 'jest'], 'default-typescript': ['app', 'vite', 'typescript', 'jest'], - 'default-esnext-plugin': ['plugin', 'webpack', 'babel', 'shadow-dom', 'jest'], - 'default-typescript-plugin': ['plugin', 'webpack', 'typescript', 'shadow-dom', 'jest'], + 'default-esnext-plugin': ['plugin', 'vite', 'babel', 'shadow-dom', 'jest'], + 'default-typescript-plugin': ['plugin', 'vite', 'typescript', 'shadow-dom', 'jest'], }; const REQUIRE_NODEJS_VESION = [14, 15, 0]; diff --git a/common/src/resource.d.ts__if_typescript b/common/src/resource.d.ts__if_typescript index ef44a5d..d3ef093 100644 --- a/common/src/resource.d.ts__if_typescript +++ b/common/src/resource.d.ts__if_typescript @@ -11,18 +11,18 @@ declare module '*.html' { } // @if css-module -declare module '*.css' { +declare module '*.module.css' { const value: Record; export default value; } // @if less -declare module '*.less' { +declare module '*.module.less' { const value: Record; export default value; } // @endif // @if sass -declare module '*.scss' { +declare module '*.module.scss' { const value: Record; export default value; } diff --git a/dumber/gulpfile.js b/dumber/gulpfile.js index c9f93e3..8934d4a 100644 --- a/dumber/gulpfile.js +++ b/dumber/gulpfile.js @@ -143,10 +143,7 @@ function buildHtml(src) { // standard DOM APIs in "closed" mode. .pipe(au2({ defaultShadowOptions: { mode: 'open' }, hmr: false })); // @endif - // @if css-module - .pipe(au2({ useCSSModule: true, hmr: false })); - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom .pipe(au2({ hmr: false })); // @endif } @@ -177,7 +174,8 @@ function buildCss(src) { // improve compatibility on svg. postcssUrl({ url: 'inline', encodeType: 'base64' }) ]))/* @if css-module */ - .pipe(cssModule())/* @endif */; + // Use .module.css naming convention + .pipe(gulpif(f => f.basename.endsWith('.module.css'), cssModule())/* @endif */; } function build() { diff --git a/jest/package.json b/jest/package.json index e98647a..26bb496 100644 --- a/jest/package.json +++ b/jest/package.json @@ -25,10 +25,7 @@ // @if shadow-dom "\\.(js|html)$": [ "@aurelia/babel-jest", { defaultShadowOptions: { mode: 'open' } } ] // @endif - // @if css-module - "\\.(js|html)$": [ "@aurelia/babel-jest", { useCSSModule: true } ] - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom "\\.(js|html)$": "@aurelia/babel-jest", // @endif // @endif @@ -36,10 +33,7 @@ // @if shadow-dom "\\.(ts|html)$": [ "@aurelia/ts-jest", { defaultShadowOptions: { mode: 'open' } } ] // @endif - // @if css-module - "\\.(ts|html)$": [ "@aurelia/ts-jest", { useCSSModule: true } ] - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom "\\.(ts|html)$": "@aurelia/ts-jest", // @endif // @endif diff --git a/parcel/README.md b/parcel/README.md index a43a97c..9eb237b 100644 --- a/parcel/README.md +++ b/parcel/README.md @@ -4,5 +4,5 @@ By Parcel2 conventions, the `index.html` is in `src/` folder. ## Aurelia 2 config -To control the behaviour of ShadownDOM and CSS-Module setup in Aurelia 2, create a section `"aurelia"` in the `package.json` file. +To control the behaviour of ShadownDOM in Aurelia 2, create a section `"aurelia"` in the `package.json` file. https://www.npmjs.com/package/@aurelia/parcel-transformer diff --git a/parcel/package.json b/parcel/package.json index c26d588..5486b68 100644 --- a/parcel/package.json +++ b/parcel/package.json @@ -45,14 +45,7 @@ "hmr": false }, // @endif - // @if css-module - "aurelia": { - "useCSSModule": true, - "hmr": false - }, - "@parcel/transformer-css": { "cssModules": true }, - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom "aurelia": { "hmr": false }, diff --git a/questions.js b/questions.js index 3641fcd..394987a 100644 --- a/questions.js +++ b/questions.js @@ -35,7 +35,7 @@ module.exports = [ {title: 'No'}, {if: 'app', value: 'shadow-dom', title: 'Use Shadow DOM', hint: 'Shadow DOM in open mode, shadowRoot is accessible through DOM API.'}, {if: 'plugin', value: 'shadow-dom', title: 'Use Shadow DOM (Recommended for plugin project)', hint: 'Shadow DOM in open mode, shadowRoot is accessible through DOM API.'}, - {value: 'css-module', title: 'Use CSS Module', hint: 'CSS Module is an alternative way to locally scope CSS class names.'}, + {value: 'css-module', title: 'Use CSS Module', hint: 'CSS Module is an alternative way to locally scope CSS class names. We use .module.css/less/scss file name convention.'}, ] }, { diff --git a/transforms.js b/transforms.js index 700cb36..2eff04f 100644 --- a/transforms.js +++ b/transforms.js @@ -8,6 +8,10 @@ exports.append = function(properties, features) { if (file.extname === '.ext') { // change .ext to .ts or .js file file.extname = features.includes('typescript') ? '.ts' : '.js'; + } else if (features.includes('css-module')) { + if (['.css', '.less', '.scss'].includes(file.extname)) { + file.extname = `.module${file.extname}`; + } } } cb(null, file); diff --git a/vite/vite.config.ext b/vite/vite.config.ext index a02923b..e3ba6f2 100644 --- a/vite/vite.config.ext +++ b/vite/vite.config.ext @@ -43,9 +43,6 @@ export default defineConfig({ // standard DOM APIs in "closed" mode. defaultShadowOptions: { mode: 'open' }, // @endif - // @if css-module - useCSSModule: true, - // @endif }), // @if babel babel(), diff --git a/webpack/webpack.config.js b/webpack/webpack.config.js index c9033af..c25c583 100644 --- a/webpack/webpack.config.js +++ b/webpack/webpack.config.js @@ -10,20 +10,6 @@ const TerserPlugin = require('terser-webpack-plugin'); const WebpackShellPluginNext = require('webpack-shell-plugin-next') // @endif -// @if !css-module -const cssLoader = 'css-loader'; -// @endif -// @if css-module -const cssLoader = { - loader: 'css-loader', - options: { - modules: true, - // https://github.com/webpack-contrib/css-loader#importloaders - importLoaders: /* @if css */1/* @endif *//* @if !css */2/* @endif */ - } -}; -// @endif - // @if sass const sassLoader = { loader: 'sass-loader', @@ -103,12 +89,12 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset' }, { test: /\.(woff|woff2|ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/i, type: 'asset' }, // @if !shadow-dom - { test: /\.css$/i, use: [ 'style-loader', cssLoader, postcssLoader ] }, + { test: /\.css$/i, use: [ 'style-loader', 'css-loader', postcssLoader ] }, // @if less - { test: /\.less$/i, use: [ 'style-loader', cssLoader, postcssLoader, 'less-loader' ] }, + { test: /\.less$/i, use: [ 'style-loader', 'css-loader', postcssLoader, 'less-loader' ] }, // @endif // @if sass - { test: /\.scss$/i, use: [ 'style-loader', cssLoader, postcssLoader, sassLoader ] }, + { test: /\.scss$/i, use: [ 'style-loader', 'css-loader', postcssLoader, sassLoader ] }, // @endif // @endif // @if shadow-dom @@ -117,7 +103,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in src/main.js, it's not loaded by style-loader. // It's for shared styles for shadow-dom only. issuer: /[/\\]src[/\\]main\.(js|ts)$/, - use: [ cssLoader, postcssLoader ] + use: [ 'css-loader', postcssLoader ] }, // @if less { @@ -125,7 +111,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in src/main.js, it's not loaded by style-loader. // It's for shared styles for shadow-dom only. issuer: /[/\\]src[/\\]main\.(js|ts)$/, - use: [ cssLoader, postcssLoader, 'less-loader' ] + use: [ 'css-loader', postcssLoader, 'less-loader' ] }, // @endif // @if sass @@ -134,7 +120,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in src/main.js, it's not loaded by style-loader. // It's for shared styles for shadow-dom only. issuer: /[/\\]src[/\\]main\.(js|ts)$/, - use: [ cssLoader, postcssLoader, sassLoader ] + use: [ 'css-loader', postcssLoader, sassLoader ] }, // @endif { @@ -142,7 +128,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in other js/ts files, it's loaded by style-loader. // They are directly injected to HTML head. issuer: /(? Date: Wed, 29 May 2024 16:32:56 +1000 Subject: [PATCH 03/17] chore: update required nodejs version --- before.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/before.js b/before.js index 6a9a43d..ba06489 100644 --- a/before.js +++ b/before.js @@ -7,7 +7,7 @@ const PRESETS = { 'default-typescript-plugin': ['plugin', 'vite', 'typescript', 'shadow-dom', 'jest'], }; -const REQUIRE_NODEJS_VESION = [14, 15, 0]; +const REQUIRE_NODEJS_VESION = [14, 17, 0]; function isNodejsOutdated() { const version = process.version.slice(1).split('.'); From f85bcc9235a5bfc2976c44703f10b043472ac0b6 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Thu, 30 May 2024 09:58:49 +1000 Subject: [PATCH 04/17] chore: update vite setup --- __test__/before-task.spec.js | 8 ++++---- before.js | 8 ++++---- vite/package.json | 12 ++++++------ vite/vite.config.ext | 3 +++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/__test__/before-task.spec.js b/__test__/before-task.spec.js index 7b19463..6a58150 100644 --- a/__test__/before-task.spec.js +++ b/__test__/before-task.spec.js @@ -23,7 +23,7 @@ test('"before" task can select default-esnext preset', async t => { const result = await before({unattended: false, prompts}); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['app', 'vite', 'babel', 'jest'] + preselectedFeatures: ['app', 'vite', 'babel', 'vitest'] }); }); @@ -40,7 +40,7 @@ test('"before" task can select default-typescript preset', async t => { const result = await before({unattended: false, prompts}); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['app', 'vite', 'typescript', 'jest'] + preselectedFeatures: ['app', 'vite', 'typescript', 'vitest'] }); }); @@ -55,7 +55,7 @@ test('"before" task can select default-esnext-plugin preset', async t => { const result = await before({ unattended: false, prompts }); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['plugin', 'vite', 'babel', 'shadow-dom', 'jest'] + preselectedFeatures: ['plugin', 'vite', 'babel', 'shadow-dom', 'vitest'] }); }); @@ -72,7 +72,7 @@ test('"before" task can select default-typescript-plugin preset', async t => { const result = await before({ unattended: false, prompts }); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['plugin', 'vite', 'typescript', 'shadow-dom', 'jest'] + preselectedFeatures: ['plugin', 'vite', 'typescript', 'shadow-dom', 'vitest'] }); }); test('"before" task can select no preset', async t => { diff --git a/before.js b/before.js index ba06489..31ac82d 100644 --- a/before.js +++ b/before.js @@ -1,10 +1,10 @@ // Use "before" task to ask user to select a preset (to skip questionnaire). const PRESETS = { - 'default-esnext': ['app', 'vite', 'babel', 'jest'], - 'default-typescript': ['app', 'vite', 'typescript', 'jest'], - 'default-esnext-plugin': ['plugin', 'vite', 'babel', 'shadow-dom', 'jest'], - 'default-typescript-plugin': ['plugin', 'vite', 'typescript', 'shadow-dom', 'jest'], + 'default-esnext': ['app', 'vite', 'babel', 'vitest'], + 'default-typescript': ['app', 'vite', 'typescript', 'vitest'], + 'default-esnext-plugin': ['plugin', 'vite', 'babel', 'shadow-dom', 'vitest'], + 'default-typescript-plugin': ['plugin', 'vite', 'typescript', 'shadow-dom', 'vitest'], }; const REQUIRE_NODEJS_VESION = [14, 17, 0]; diff --git a/vite/package.json b/vite/package.json index 2842ede..bb8eca4 100644 --- a/vite/package.json +++ b/vite/package.json @@ -2,23 +2,23 @@ "type": "module", "devDependencies": { "@aurelia/vite-plugin": /* @if latest */"latest"/* @endif *//* @if dev */"dev"/* @endif */, - "vite": "^5.1.4", - "vite-plugin-node-polyfills": "^0.21.0", + "vite": "^5.2.12", + "vite-plugin-node-polyfills": "^0.22.0", // @if babel "vite-plugin-babel": "^1.2.0", // @endif // @if typescript && plugin - "vite-plugin-dts": "^3.8.1", + "vite-plugin-dts": "^3.9.1", // @endif // @if vitest - "vitest": "^1.4.0", - "jsdom": "^24.0.0", + "vitest": "^1.6.0", + "jsdom": "^24.1.0", // @endif // @if less "less": "^4.2.0", // @endif // @if sass - "sass": "^1.72.0", + "sass": "^1.77.3", // @endif }, "scripts": { diff --git a/vite/vite.config.ext b/vite/vite.config.ext index e3ba6f2..8e56609 100644 --- a/vite/vite.config.ext +++ b/vite/vite.config.ext @@ -16,6 +16,9 @@ export default defineConfig({ open: !process.env.CI, port: 9000, }, + esbuild: { + target: 'es2022' + }, // @if plugin build: { lib: { From 2d59f9cbdf6e2d471c06431c29789f5bb5ba6bf3 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 13:46:44 +1000 Subject: [PATCH 05/17] chore: update plugin unit test --- plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext b/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext index 50debb7..4740cec 100644 --- a/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext +++ b/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext @@ -1,6 +1,9 @@ // @if mocha import { expect } from 'chai'; // @endif +// @if vitest +import { describe, it, expect } from 'vitest'; +// @endif // @if shadow-dom import { CustomElement } from 'aurelia'; // @endif @@ -25,7 +28,7 @@ describe('hello-world', () => { // @if !shadow-dom const text = node.textContent; // @endif - // @if jasmine || jest + // @if jasmine || jest || vitest expect(text.trim()).toBe('Hello World! foo'); // @endif // @if mocha From c7d4c6d81bd32e88ba70407177da2a52e8f9cb26 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 13:55:17 +1000 Subject: [PATCH 06/17] chore: ts v5.5 has some issue on type infer for our decorator --- typescript/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/package.json b/typescript/package.json index 95e9b5d..a1e9f28 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,7 +1,7 @@ { "devDependencies": { "@types/node": "^20.12.3", - "typescript": "^5.4.3", + "typescript": "~5.4.5", "tslib": "^2.6.2", "@typescript-eslint/eslint-plugin": "^7.5.0", "@typescript-eslint/parser": "^7.5.0" From 475cd8adda7e60dc0a9672169be86c7abe0fd88f Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 14:24:29 +1000 Subject: [PATCH 07/17] fix: move plugin setup to webpack for now, vite has limitation --- __test__/before-task.spec.js | 4 ++-- before.js | 11 ++++++++--- common/package.json | 3 ++- questions.js | 4 ++-- typescript/package.json | 1 + 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/__test__/before-task.spec.js b/__test__/before-task.spec.js index 6a58150..19576d2 100644 --- a/__test__/before-task.spec.js +++ b/__test__/before-task.spec.js @@ -55,7 +55,7 @@ test('"before" task can select default-esnext-plugin preset', async t => { const result = await before({ unattended: false, prompts }); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['plugin', 'vite', 'babel', 'shadow-dom', 'vitest'] + preselectedFeatures: ['plugin', 'webpack', 'babel', 'shadow-dom', 'jest'] }); }); @@ -72,7 +72,7 @@ test('"before" task can select default-typescript-plugin preset', async t => { const result = await before({ unattended: false, prompts }); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['plugin', 'vite', 'typescript', 'shadow-dom', 'vitest'] + preselectedFeatures: ['plugin', 'webpack', 'typescript', 'shadow-dom', 'jest'] }); }); test('"before" task can select no preset', async t => { diff --git a/before.js b/before.js index 31ac82d..47b734c 100644 --- a/before.js +++ b/before.js @@ -3,11 +3,16 @@ const PRESETS = { 'default-esnext': ['app', 'vite', 'babel', 'vitest'], 'default-typescript': ['app', 'vite', 'typescript', 'vitest'], - 'default-esnext-plugin': ['plugin', 'vite', 'babel', 'shadow-dom', 'vitest'], - 'default-typescript-plugin': ['plugin', 'vite', 'typescript', 'shadow-dom', 'vitest'], + // TODO: move plugin to vite+vitest + // FIXME: vite compiles plugin with separate css dist file, and removed + // import('./style.css') from js code, need to: + // 1. hook up a css loader in runtime for normal css and css-module. + // 2. hook up a text loader in runtime for shadow-dom css. + 'default-esnext-plugin': ['plugin', 'webpack', 'babel', 'shadow-dom', 'jest'], + 'default-typescript-plugin': ['plugin', 'webpack', 'typescript', 'shadow-dom', 'jest'], }; -const REQUIRE_NODEJS_VESION = [14, 17, 0]; +const REQUIRE_NODEJS_VESION = [18, 0, 0]; function isNodejsOutdated() { const version = process.version.slice(1).split('.'); diff --git a/common/package.json b/common/package.json index fcbfbb6..246a4d4 100644 --- a/common/package.json +++ b/common/package.json @@ -5,7 +5,8 @@ // @endif // @if plugin "description": "An Aurelia 2 plugin.", - "type": "module", + // TODO: turn on after moved plugin to vite steup + // "type": "module", "main": "dist/index.js", "files": [ "dist" diff --git a/questions.js b/questions.js index 394987a..a470859 100644 --- a/questions.js +++ b/questions.js @@ -16,8 +16,8 @@ module.exports = [ { message: 'Which bundler would you like to use?', choices: [ - {value: 'vite', title: 'Vite', hint: 'Next Generation Frontend Tooling.'}, - {if: 'app', value: 'webpack', title: 'Webpack', hint: 'A powerful and popular bundler for modern JavaScript apps.'}, + {if: 'app', value: 'vite', title: 'Vite', hint: 'Next Generation Frontend Tooling.'}, + {value: 'webpack', title: 'Webpack', hint: 'A powerful and popular bundler for modern JavaScript apps.'}, {if: 'app', value: 'dumber', title: 'Dumber', hint: 'A dumb JavasScript bundler, dumber than you and me. The successor of Aurelia CLI built-in bundler.'}, {if: 'app', value: 'parcel', title: 'Parcel', hint: 'Blazing fast, zero configuration web application bundler.'}, ] diff --git a/typescript/package.json b/typescript/package.json index a1e9f28..56c29cc 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,7 @@ { "devDependencies": { "@types/node": "^20.12.3", + // FIXME: typescript v5.5 has issue with our decorator typing "typescript": "~5.4.5", "tslib": "^2.6.2", "@typescript-eslint/eslint-plugin": "^7.5.0", From 446a68abd2d5f2a1513e5a4a2e40321e96b064f5 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 14:41:33 +1000 Subject: [PATCH 08/17] chore: recover webpack plugin setup --- webpack/package.json | 3 +++ webpack/webpack.config.js | 44 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/webpack/package.json b/webpack/package.json index 70f8b76..bd76e89 100644 --- a/webpack/package.json +++ b/webpack/package.json @@ -29,6 +29,9 @@ // @if jasmine || mocha "webpack-shell-plugin-next": "^2.3.1", // @endif + // @if plugin + "webpack-node-externals": "^3.0.0", + // @endif }, "scripts": { "start": "webpack serve", diff --git a/webpack/webpack.config.js b/webpack/webpack.config.js index c25c583..eac1478 100644 --- a/webpack/webpack.config.js +++ b/webpack/webpack.config.js @@ -9,6 +9,9 @@ const TerserPlugin = require('terser-webpack-plugin'); // @if jasmine || mocha const WebpackShellPluginNext = require('webpack-shell-plugin-next') // @endif +// @if plugin +const nodeExternals = require('webpack-node-externals'); +// @endif // @if sass const sassLoader = { @@ -36,7 +39,12 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a const test = env.test || process.env.NODE_ENV === 'test'; // @endif return { + // @if app target: 'web', + // @endif + // @if plugin + target: production ? 'node' : 'web', + // @endif mode: production ? 'production' : 'development', devtool: production ? undefined : 'eval-source-map', optimization: { @@ -56,22 +64,42 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a entry: { entry: test ? './test/all-spec./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' : + // @if app './src/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' + // @endif + // @if plugin + // Build only plugin in production mode, + // build dev-app in non-production mode + (production ? './src/index./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' : './dev-app/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */') + // @endif }, // @endif // @if !jasmine && !mocha entry: { + // @if app entry: './src/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' + // @endif + // @if plugin + // Build only plugin in production mode, + // build dev-app in non-production mode + entry: production? './src/index./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' : './dev-app/main./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */' + // @endif }, // @endif output: { clean: true, path: path.resolve(__dirname, 'dist'), + // @if app filename: production ? '[name].[contenthash].bundle.js' : '[name].bundle.js' + // @endif + // @if plugin + filename: production ? 'index.js' : '[name].bundle.js', + library: production ? { type: 'commonjs' } : undefined + // @endif }, resolve: { extensions: [/* @if typescript */'.ts', /* @endif */'.js'], - modules: [path.resolve(__dirname, 'src'), 'node_modules'], + modules: [path.resolve(__dirname, 'src'),/* @if plugin */ path.resolve(__dirname, 'dev-app'),/* @endif */ 'node_modules'], alias: production ? { // add your production aliases here } : { @@ -178,7 +206,12 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a { test: /\.ts$/i, use: ['ts-loader', '@aurelia/webpack-loader'], exclude: /node_modules/ }, // @endif { + // @if app test: /[/\\]src[/\\].+\.html$/i, + // @endif + // @if plugin + test: /[/\\](?:src|dev-app)[/\\].+\.html$/i, + // @endif // @if shadow-dom use: { loader: '@aurelia/webpack-loader', @@ -198,8 +231,15 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a } ] }, + // @if plugin + externalsPresets: { node: production }, + externals: [ + // Skip npm dependencies in plugin build. + production && nodeExternals() + ].filter(p => p), + // @endif plugins: [ - new HtmlWebpackPlugin({ template: 'index.html', favicon: 'favicon.ico' }), + /* @if plugin */!production && /* @endif */new HtmlWebpackPlugin({ template: 'index.html', favicon: 'favicon.ico' }), new Dotenv({ path: `./.env${production ? '' : '.' + (process.env.NODE_ENV || 'development')}`, }), From 39e1ce8ef2ff6677730f27711373672342d232a6 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 15:28:07 +1000 Subject: [PATCH 09/17] chore: missing ) --- dumber/gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dumber/gulpfile.js b/dumber/gulpfile.js index 8934d4a..3e80400 100644 --- a/dumber/gulpfile.js +++ b/dumber/gulpfile.js @@ -175,7 +175,7 @@ function buildCss(src) { postcssUrl({ url: 'inline', encodeType: 'base64' }) ]))/* @if css-module */ // Use .module.css naming convention - .pipe(gulpif(f => f.basename.endsWith('.module.css'), cssModule())/* @endif */; + .pipe(gulpif(f => f.basename.endsWith('.module.css'), cssModule()))/* @endif */; } function build() { From b519626c2dcea3dff3beb5d0080bd6e0d9afedec Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 15:30:18 +1000 Subject: [PATCH 10/17] chore: vite e2e matcher --- e2e-test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e-test.js b/e2e-test.js index 2f596e1..96bb6d2 100644 --- a/e2e-test.js +++ b/e2e-test.js @@ -111,6 +111,7 @@ if (targetFeatures.length) { function getServerRegex(features) { if (features.includes('webpack')) return /Loopback: (\S+)/; if (features.includes('parcel')) return /Server running at (\S+)/; + if (features.includes('vite')) return /Local:\s+(\S+)/; return /Dev server is started at: (\S+)/; } From 38bbfa0e709d77a7acbb87247105c8082c03081f Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 16:20:18 +1000 Subject: [PATCH 11/17] chore: update vite e2e --- e2e-test.js | 25 ++----------------------- package.json | 1 - 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/e2e-test.js b/e2e-test.js index 96bb6d2..d2d245b 100644 --- a/e2e-test.js +++ b/e2e-test.js @@ -9,7 +9,6 @@ const os = require('os'); const fs = require('fs'); const path = require('path'); const test = require('ava'); -const puppeteer = require('puppeteer'); const kill = require('tree-kill'); const {possibleFeatureSelections} = require('makes'); const questions = require('./questions'); @@ -85,15 +84,6 @@ function run(command, dataCB, errorCB) { }); } -async function takeScreenshot(url, filePath) { - const browser = await puppeteer.launch(); - const page = await browser.newPage(); - await page.goto(url); - await new Promise(r => setTimeout(r, 6000)); - await page.screenshot({path: filePath}); - await browser.close(); -} - const targetFeatures = (process.env.TARGET_FEATURES || '').toLowerCase().split(',').filter(p => p); if (!targetFeatures.includes('playwright')) { targetFeatures.push('playwright'); @@ -111,7 +101,7 @@ if (targetFeatures.length) { function getServerRegex(features) { if (features.includes('webpack')) return /Loopback: (\S+)/; if (features.includes('parcel')) return /Server running at (\S+)/; - if (features.includes('vite')) return /Local:\s+(\S+)/; + if (features.includes('vite')) return /(http:\/\/\S+\/)/; return /Dev server is started at: (\S+)/; } @@ -164,18 +154,7 @@ skeletons.forEach((features, i) => { const m = data.toString().match(serverRegex); if (!m) return; const url = m[1]; - t.pass(m[0]); - - try { - if (!process.env.GITHUB_ACTIONS) { - console.log('-- take screenshot'); - await takeScreenshot(url, path.join(folder, appName + '.png')); - } - kill(); - } catch (e) { - t.fail(e.message); - kill(); - } + t.pass(m[0]); kill(); }; // Webpack5 now prints Loopback: http://localhost:5000 in stderr! diff --git a/package.json b/package.json index 35640c7..abe82d4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "glob": "^10.3.1", "makes": "^3.2.0", "npm-check-updates": "^16.10.13", - "puppeteer": "^20.7.3", "semver": "^7.5.3", "standard-changelog": "^3.0.0", "tree-kill": "^1.2.2", From efe770cac8f873a95582b161315358906e9ac1c1 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Wed, 10 Jul 2024 16:59:08 +1000 Subject: [PATCH 12/17] chore: playwright config in esm --- .../app.spec.ext__if_not_plugin | 5 ----- ...right.config.ext => playwright.config.mjs} | 20 +++---------------- 2 files changed, 3 insertions(+), 22 deletions(-) rename playwright/{playwright.config.ext => playwright.config.mjs} (86%) diff --git a/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin b/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin index 9e747ef..ff58ddf 100644 --- a/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin +++ b/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin @@ -1,9 +1,4 @@ -// @if typescript import { test, expect } from '@playwright/test'; -// @endif -// @if babel -const { test, expect } = require('@playwright/test'); -// @endif test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9000'); diff --git a/playwright/playwright.config.ext b/playwright/playwright.config.mjs similarity index 86% rename from playwright/playwright.config.ext rename to playwright/playwright.config.mjs index 2edccd3..26d7224 100644 --- a/playwright/playwright.config.ext +++ b/playwright/playwright.config.mjs @@ -1,11 +1,4 @@ -// @if typescript -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; -// @endif -// @if babel -// @ts-check -const { devices } = require('@playwright/test'); -// @endif +import { defineConfig, devices } from '@playwright/test'; /** * Read environment variables from file. @@ -16,7 +9,7 @@ const { devices } = require('@playwright/test'); /** * See https://playwright.dev/docs/test-configuration. */ -const config/* @if typescript */: PlaywrightTestConfig/* @endif */ = { +export default defineConfig({ testDir: './e2e', /* Maximum time one test can run for. */ timeout: 30 * 1000, @@ -108,11 +101,4 @@ const config/* @if typescript */: PlaywrightTestConfig/* @endif */ = { command: 'npm start', port: 9000, }, -}; - -// @if typescript -export default config; -// @endif -// @if babel -module.exports = config; -// @endif +}); From 5f5820814ff46c28dd2a4b4aae3b3341d2a7f80f Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Thu, 11 Jul 2024 10:38:07 +1000 Subject: [PATCH 13/17] fix: no tsconfig for vitest if not using ts --- ...__if_vitest => tsconfig.vitest.json__if_vitest_and_typescript} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vite/{tsconfig.vitest.json__if_vitest => tsconfig.vitest.json__if_vitest_and_typescript} (100%) diff --git a/vite/tsconfig.vitest.json__if_vitest b/vite/tsconfig.vitest.json__if_vitest_and_typescript similarity index 100% rename from vite/tsconfig.vitest.json__if_vitest rename to vite/tsconfig.vitest.json__if_vitest_and_typescript From 6d5bcf3d39c4c1e83e684a4fa80ac3c84d0a9e48 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Sat, 13 Jul 2024 16:49:38 +1000 Subject: [PATCH 14/17] chore: try dev release with vite+windows --- .github/workflows/e2e-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-windows.yml b/.github/workflows/e2e-windows.yml index c5dfce4..115f28f 100644 --- a/.github/workflows/e2e-windows.yml +++ b/.github/workflows/e2e-windows.yml @@ -26,8 +26,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript - - latest,vite,babel - - latest,vite,typescript + - dev,vite,babel + - dev,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} From 5b335e59dacaf6f0d8d9db2fcce191eba9236f93 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Fri, 9 Aug 2024 10:55:34 +1000 Subject: [PATCH 15/17] Revert "chore: try dev release with vite+windows" This reverts commit 6d5bcf3d39c4c1e83e684a4fa80ac3c84d0a9e48. --- .github/workflows/e2e-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-windows.yml b/.github/workflows/e2e-windows.yml index 115f28f..c5dfce4 100644 --- a/.github/workflows/e2e-windows.yml +++ b/.github/workflows/e2e-windows.yml @@ -26,8 +26,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript - - dev,vite,babel - - dev,vite,typescript + - latest,vite,babel + - latest,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} From 3408a2496ea360babce29762df57f54cba25f583 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Fri, 9 Aug 2024 12:10:53 +1000 Subject: [PATCH 16/17] chore: win32+vite+spawn seems having issue with process.chdir --- e2e-test.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/e2e-test.js b/e2e-test.js index d2d245b..70e9e6a 100644 --- a/e2e-test.js +++ b/e2e-test.js @@ -39,7 +39,7 @@ function killProc(proc) { kill(proc.pid); } -function run(command, dataCB, errorCB) { +function run(command, cwd, dataCB, errorCB) { const [cmd, ...args] = command.split(' '); return new Promise((resolve, reject) => { const env = Object.create(process.env); @@ -48,7 +48,7 @@ function run(command, dataCB, errorCB) { // need to reset NODE_ENV back to development because this whole // test is running in NODE_ENV=test which will affect gulp build env.NODE_ENV = 'development'; - const proc = spawn(cmd, args, {env}); + const proc = spawn(cmd, args, {env, cwd}); proc.on('exit', async (code, signal) => { await delay(1); if (code && signal !== 'SIGTERM' && !win32Killed.has(proc.pid)) { @@ -117,26 +117,24 @@ skeletons.forEach((features, i) => { test.serial(title, async t => { console.log(title); - process.chdir(folder); const makeCmd = `npx makes ${__dirname} ${appName} -s ${features.join(',')}`; console.log('-- ' + makeCmd); - await run(makeCmd); + await run(makeCmd, folder); t.pass('made skeleton'); - process.chdir(appFolder); console.log('-- npm i'); - await run('npm i'); + await run('npm i', appFolder); t.pass('installed deps'); if (!features.includes('no-unit-tests')) { console.log('-- npm test'); - await run('npm test'); + await run('npm test', appFolder); t.pass('finished unit tests'); } console.log('-- npm run build'); - await run('npm run build', null, + await run('npm run build', appFolder, null, (data, kill) => { // Skip parcel warnings. if (features.includes('parcel')) return; @@ -154,22 +152,22 @@ skeletons.forEach((features, i) => { const m = data.toString().match(serverRegex); if (!m) return; const url = m[1]; - t.pass(m[0]); kill(); + t.pass(m[0]); + kill(); }; // Webpack5 now prints Loopback: http://localhost:5000 in stderr! - await run('npm start', runE2e, runE2e); + await run('npm start', appFolder, runE2e, runE2e); if (features.includes('playwright')) { console.log('-- npx playwright test --project chromium'); - await run('npx playwright install --with-deps'); - await run('npx playwright test --project chromium'); + await run('npx playwright install --with-deps', appFolder); + await run('npx playwright test --project chromium', appFolder); } await delay(1); console.log('-- remove folder ' + appName); - process.chdir(folder); await fs.promises.rm(appFolder, {recursive: true}); }); }); From 566497da8b1ddf8a54f599b99791e6d915731402 Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Fri, 9 Aug 2024 15:22:14 +1000 Subject: [PATCH 17/17] chore: try local e2e --- e2e-test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/e2e-test.js b/e2e-test.js index 70e9e6a..084ce37 100644 --- a/e2e-test.js +++ b/e2e-test.js @@ -5,7 +5,6 @@ // Have to run "npm run test:e2e" manually before a release. const spawn = require('cross-spawn'); -const os = require('os'); const fs = require('fs'); const path = require('path'); const test = require('ava'); @@ -23,7 +22,7 @@ const allSkeletons = possibleFeatureSelections(questions); const isWin32 = process.platform === 'win32'; -const folder = path.join(os.tmpdir(), 'test-skeletons'); +const folder = path.join(__dirname, 'test-skeletons'); console.log('-- cleanup ' + folder); fs.rmSync(folder, {recursive: true, force: true}); fs.mkdirSync(folder);