From dc59abda61bb1bc27956c047a759485f4b5ca51f Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Fri, 26 Feb 2021 15:39:24 +0100 Subject: [PATCH 1/8] fix(webpack): ignore source-maps in total asset size --- packages/webpack/lib/plugins/log.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/webpack/lib/plugins/log.js b/packages/webpack/lib/plugins/log.js index e9af5140e..0a0579bcd 100644 --- a/packages/webpack/lib/plugins/log.js +++ b/packages/webpack/lib/plugins/log.js @@ -46,10 +46,11 @@ const formatWarning = (name, duration, assets, isRebuild) => { }; const formatSuccess = (name, duration, assets, isRebuild) => { - const totalSize = Object.values(assets).reduce( - (sum, asset) => sum + asset.size, - 0 - ); + const totalSize = Object.values(assets) + .filter((asset) => !asset.name.endsWith('.map')) + .reduce((sum, asset) => { + return sum + asset.size; + }, 0); const message = `bundling '${name}' finished after ${duration} (${prettyBytes( totalSize )})`; From 1746b4da07b53c2b37815916bc8ed14aa24a6d1a Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Fri, 26 Feb 2021 15:40:35 +0100 Subject: [PATCH 2/8] feat(webpack): introduce experimental esbuild transpilation --- packages/webpack/mixins/build/mixin.core.js | 5 ++ packages/webpack/mixins/esbuild/mixin.core.js | 54 +++++++++++++++++++ .../mixins/optimizations/mixin.core.js | 24 ++++++--- packages/webpack/mixins/start/mixin.core.js | 5 ++ packages/webpack/preset.js | 1 + 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 packages/webpack/mixins/esbuild/mixin.core.js diff --git a/packages/webpack/mixins/build/mixin.core.js b/packages/webpack/mixins/build/mixin.core.js index ccae446fb..1003b3fa3 100644 --- a/packages/webpack/mixins/build/mixin.core.js +++ b/packages/webpack/mixins/build/mixin.core.js @@ -127,6 +127,11 @@ class WebpackBuildMixin extends Mixin { describe: 'Run webpack builds in parallel', type: 'boolean', }, + experimentalEsbuild: { + default: process.env.USE_EXPERIMENTAL_ESBUILD === 'true', + describe: 'Use esbuild for transpilation (experimental)', + type: 'boolean', + }, }, handler: (argv) => Promise.resolve(argv.clean && this.clean()) diff --git a/packages/webpack/mixins/esbuild/mixin.core.js b/packages/webpack/mixins/esbuild/mixin.core.js new file mode 100644 index 000000000..2be0c1dd0 --- /dev/null +++ b/packages/webpack/mixins/esbuild/mixin.core.js @@ -0,0 +1,54 @@ +const { Mixin } = require('hops-mixin'); + +class HopsEsbuildMixin extends Mixin { + configureBuild(webpackConfig, { jsLoaderConfig }, target) { + const { experimentalEsbuild } = this.options; + + if (!experimentalEsbuild) { + return; + } + + // NOTE: We don't want to ship esbuild, so we just assume it is installed + // when someone wants to use it. + // eslint-disable-next-line node/no-missing-require, node/no-extraneous-require + const { ESBuildMinifyPlugin } = require('esbuild-loader'); + const esbuildTarget = target === 'node' ? 'node12' : 'es2015'; + const { test, include, exclude, ...rest } = jsLoaderConfig; + Object.keys(rest).forEach((key) => delete jsLoaderConfig[key]); + Object.assign(jsLoaderConfig, { + test, + include, + exclude, + use: [ + { + loader: 'esbuild-loader', + options: { + loader: 'js', + target: esbuildTarget, + }, + }, + ], + }); + + // NOTE: We don't decide here whether to minify or not but instead just + // override it if someone else has already configured it. + if ( + Array.isArray(webpackConfig.optimization.minimizer) && + webpackConfig.optimization.minimizer.length > 0 + ) { + webpackConfig.optimization.minimizer = [ + new ESBuildMinifyPlugin({ + target: esbuildTarget, + minify: true, + sourcemap: true, + }), + ]; + } + } + + handleArguments(argv) { + this.options = { ...this.options, ...argv }; + } +} + +module.exports = HopsEsbuildMixin; diff --git a/packages/webpack/mixins/optimizations/mixin.core.js b/packages/webpack/mixins/optimizations/mixin.core.js index 97c8b2643..c292e1704 100644 --- a/packages/webpack/mixins/optimizations/mixin.core.js +++ b/packages/webpack/mixins/optimizations/mixin.core.js @@ -25,7 +25,12 @@ function findResolved(a, b) { class WebpackOptimizationsMixin extends Mixin { configureBuild(webpackConfig, { allLoaderConfigs, jsLoaderConfig }, target) { - const { fastBuild: fastBuildFlag, fastDev: fastDevFlag } = this.options; + const { + fastBuild: fastBuildFlag, + fastDev: fastDevFlag, + experimentalEsbuild, + } = this.options; + const { NODE_ENV } = process.env; const fastBuild = fastBuildFlag && (target === 'build' || target === 'node'); @@ -34,17 +39,24 @@ class WebpackOptimizationsMixin extends Mixin { NODE_ENV !== 'production' && (target === 'develop' || target === 'node'); - const [, presetEnvOptions] = - jsLoaderConfig.options.presets - .filter(Array.isArray) - .find(([path]) => findResolved(path, '@babel/preset-env')) || []; - if (fastBuild || fastDev) { // do not transpile node_modules for either fastBuild or fastDev const { experimental: { babelIncludePatterns = [] } = {} } = this.config; jsLoaderConfig.include = include(babelIncludePatterns); jsLoaderConfig.exclude = []; + } + if (experimentalEsbuild) { + // Do not apply any other options as they are for Babel. + return; + } + + const [, presetEnvOptions] = + jsLoaderConfig.options.presets + .filter(Array.isArray) + .find(([path]) => findResolved(path, '@babel/preset-env')) || []; + + if (fastBuild || fastDev) { // always add "regenerator-runtime/runtime" because babel will still down- // transpile async functions if the browserslist requires it webpackConfig.entry = [require.resolve('regenerator-runtime/runtime')] diff --git a/packages/webpack/mixins/start/mixin.core.js b/packages/webpack/mixins/start/mixin.core.js index f725397c1..8701c0561 100644 --- a/packages/webpack/mixins/start/mixin.core.js +++ b/packages/webpack/mixins/start/mixin.core.js @@ -27,6 +27,11 @@ class WebpackStartMixin extends Mixin { 'Experimental: Enable faster development mode (modern browsers only)', type: 'boolean', }, + experimentalEsbuild: { + default: process.env.USE_EXPERIMENTAL_ESBUILD === 'true', + describe: 'Use esbuild for transpilation (experimental)', + type: 'boolean', + }, }, handler: (argv) => { if (process.env.NODE_ENV === 'production') { diff --git a/packages/webpack/preset.js b/packages/webpack/preset.js index 57fe42634..86a29d82b 100644 --- a/packages/webpack/preset.js +++ b/packages/webpack/preset.js @@ -18,6 +18,7 @@ module.exports = { join(__dirname, 'mixins', 'render'), join(__dirname, 'mixins', 'start'), join(__dirname, 'mixins', 'stats'), + join(__dirname, 'mixins', 'esbuild'), join(__dirname, 'mixins', 'optimizations'), ], mixinTypes: { From 13028d2946cabb39d9482894bf2361fd7a77f8e3 Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Fri, 5 Mar 2021 15:06:25 +0100 Subject: [PATCH 3/8] feat(typescript): add support for esbuild --- packages/typescript/mixin.core.js | 87 ++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 19 deletions(-) diff --git a/packages/typescript/mixin.core.js b/packages/typescript/mixin.core.js index a4f095083..95a6604f8 100644 --- a/packages/typescript/mixin.core.js +++ b/packages/typescript/mixin.core.js @@ -28,29 +28,78 @@ const getCompilerOptions = (ts, rootPath) => { class TypescriptMixin extends Mixin { configureBuild(webpackConfig, { jsLoaderConfig, allLoaderConfigs }, target) { - const { loader, options, exclude } = jsLoaderConfig; - const isDevelop = - target === 'develop' || - (target === 'node' && process.env.NODE_ENV !== 'production'); - const loaderOptions = isDevelop - ? { compilerOptions: { isolatedModules: true }, transpileOnly: true } - : undefined; + const { experimentalEsbuild } = this.options; - allLoaderConfigs.unshift({ - test: /\.tsx?$/, - exclude, - use: [ + webpackConfig.resolve.extensions.push('.ts', '.tsx'); + + if (experimentalEsbuild) { + const { + include, + exclude, + use: [{ loader, options }, ...loaders], + } = jsLoaderConfig; + + allLoaderConfigs.unshift( { - loader, - options, + test: /\.ts$/, + include, + exclude, + use: [ + { + loader, + options: { + ...options, + loader: 'ts', + }, + }, + ...loaders, + ], }, { - loader: require.resolve('ts-loader'), - options: loaderOptions, - }, - ], - }); - webpackConfig.resolve.extensions.push('.ts', '.tsx'); + test: /\.tsx$/, + include, + exclude, + use: [ + { + loader, + options: { + ...options, + loader: 'tsx', + }, + }, + ...loaders, + ], + } + ); + } else { + const { exclude, loader, options } = jsLoaderConfig; + + const isDevelop = + target === 'develop' || + (target === 'node' && process.env.NODE_ENV !== 'production'); + const loaderOptions = isDevelop + ? { compilerOptions: { isolatedModules: true }, transpileOnly: true } + : undefined; + + allLoaderConfigs.unshift({ + test: /\.tsx?$/, + exclude, + use: [ + { + loader, + options, + }, + { + loader: require.resolve('ts-loader'), + options: loaderOptions, + }, + ], + }); + } + } + + handleArguments(argv) { + this.options = { ...this.options, ...argv }; } diagnose() { From 6a416a8c981c841ca2ec799ea7c51f5097fe4793 Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Fri, 5 Mar 2021 16:06:38 +0100 Subject: [PATCH 4/8] feat(react): add support for esbuild --- packages/react/build/mixin.core.js | 28 +++++++++++++------ .../import-component-loader.js | 10 +++++++ packages/react/import-component/mixin.core.js | 18 +++++++++--- 3 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 packages/react/import-component/import-component-loader.js diff --git a/packages/react/build/mixin.core.js b/packages/react/build/mixin.core.js index 1ed053740..d64b7a96e 100644 --- a/packages/react/build/mixin.core.js +++ b/packages/react/build/mixin.core.js @@ -2,24 +2,36 @@ const { Mixin } = require('hops-mixin'); class ReactCoreMixin extends Mixin { configureBuild(webpackConfig, { fileLoaderConfig, jsLoaderConfig }, target) { + const { experimentalEsbuild } = this.options; + webpackConfig.resolve.extensions.push('.jsx'); fileLoaderConfig.exclude.push(/\.jsx$/); jsLoaderConfig.test.push(/\.jsx$/); - jsLoaderConfig.options.presets.push(require.resolve('@babel/preset-react')); - - jsLoaderConfig.options.plugins.push( - require.resolve('@babel/plugin-transform-flow-strip-types'), - require.resolve('@babel/plugin-proposal-class-properties') - ); + if (experimentalEsbuild) { + jsLoaderConfig.use[0].options.loader = 'jsx'; + } else { + jsLoaderConfig.options.presets.push( + require.resolve('@babel/preset-react') + ); - if (target !== 'develop' && process.env.NODE_ENV === 'production') { jsLoaderConfig.options.plugins.push( - require.resolve('babel-plugin-transform-react-remove-prop-types') + require.resolve('@babel/plugin-transform-flow-strip-types'), + require.resolve('@babel/plugin-proposal-class-properties') ); + + if (target !== 'develop' && process.env.NODE_ENV === 'production') { + jsLoaderConfig.options.plugins.push( + require.resolve('babel-plugin-transform-react-remove-prop-types') + ); + } } } + handleArguments(argv) { + this.options = { ...this.options, ...argv }; + } + diagnose({ detectDuplicatePackages }) { detectDuplicatePackages('react', 'react-dom'); } diff --git a/packages/react/import-component/import-component-loader.js b/packages/react/import-component/import-component-loader.js new file mode 100644 index 000000000..641ea349e --- /dev/null +++ b/packages/react/import-component/import-component-loader.js @@ -0,0 +1,10 @@ +const regex = /importComponent\s*\(\s*\(\)\s+=>\s+import\(\s*'([^']+)'\s*\)\s*\)/g; + +function importComponentLoader(source) { + return source.replace( + regex, + "importComponent({ load: () => import('$1'), moduleId: require.resolveWeak('$1') })" + ); +} + +module.exports = importComponentLoader; diff --git a/packages/react/import-component/mixin.core.js b/packages/react/import-component/mixin.core.js index 2582c6594..1a0fcbc4f 100644 --- a/packages/react/import-component/mixin.core.js +++ b/packages/react/import-component/mixin.core.js @@ -2,10 +2,20 @@ const { Mixin } = require('hops-mixin'); class ImportComponentCoreMixin extends Mixin { configureBuild(webpackConfig, { jsLoaderConfig }) { - jsLoaderConfig.options.plugins.push([ - require.resolve('../lib/babel'), - { module: 'hops' }, - ]); + const { experimentalEsbuild } = this.options; + + if (experimentalEsbuild) { + jsLoaderConfig.use.push(require.resolve('./import-component-loader.js')); + } else { + jsLoaderConfig.options.plugins.push([ + require.resolve('../lib/babel'), + { module: 'hops' }, + ]); + } + } + + handleArguments(argv) { + this.options = { ...this.options, ...argv }; } } From 52200186f9d94dd60c010331601721efb58f8e9e Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Fri, 5 Mar 2021 16:07:29 +0100 Subject: [PATCH 5/8] chore(styled-components): warn when esbuild is used as we do not support styled components yet --- packages/styled-components/mixin.core.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/styled-components/mixin.core.js b/packages/styled-components/mixin.core.js index e97c11867..fdfdf5817 100644 --- a/packages/styled-components/mixin.core.js +++ b/packages/styled-components/mixin.core.js @@ -2,6 +2,15 @@ const { Mixin } = require('hops-mixin'); class StyledComponentsMixin extends Mixin { configureBuild(webpackConfig, { jsLoaderConfig }, target) { + const { experimentalEsbuild } = this.options; + + if (experimentalEsbuild) { + console.warn( + 'The experimental esbuild transpilation does not support styled components yet!' + ); + return; + } + jsLoaderConfig.options.plugins.unshift([ require.resolve('babel-plugin-styled-components'), { @@ -12,6 +21,10 @@ class StyledComponentsMixin extends Mixin { }, ]); } + + handleArguments(argv) { + this.options = { ...this.options, ...argv }; + } } module.exports = StyledComponentsMixin; From 6a2845e6d2daf096edc1d61c59d65cdb68fc0391 Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Thu, 4 Mar 2021 17:37:33 +0100 Subject: [PATCH 6/8] feat(jest-preset): introduce experimental esbuild transpilation --- packages/jest-preset/jest-preset.js | 28 +++++++++++++++------- packages/jest-preset/transforms/esbuild.js | 17 +++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 packages/jest-preset/transforms/esbuild.js diff --git a/packages/jest-preset/jest-preset.js b/packages/jest-preset/jest-preset.js index 14d7eee7f..9cb866d9e 100644 --- a/packages/jest-preset/jest-preset.js +++ b/packages/jest-preset/jest-preset.js @@ -17,12 +17,22 @@ if (Number(jestMajorVersion) < 26) { ); } +const useEsbuild = process.env.USE_EXPERIMENTAL_ESBUILD === 'true'; +const jsTransform = useEsbuild + ? require.resolve('./transforms/esbuild.js') + : require.resolve('./transforms/babel.js'); +const tsTransform = useEsbuild + ? require.resolve('./transforms/esbuild.js') + : require.resolve('ts-jest'); + module.exports = { - globals: { - 'ts-jest': { - babelConfig: require('./transforms/babel.js').babelConfig, - }, - }, + globals: useEsbuild + ? {} + : { + 'ts-jest': { + babelConfig: require('./transforms/babel.js').babelConfig, + }, + }, moduleNameMapper: { '^.+\\.(png|gif|jpe?g|webp|html|svg|((o|t)tf)|woff2?|ico)$': require.resolve( './mocks/file.js' @@ -37,12 +47,14 @@ module.exports = { '**/?(*.)+(spec|test).ts?(x)', ], transform: { - '^.+\\.(js|jsx|mjs)$': require.resolve('./transforms/babel.js'), - '^.+\\.(ts|tsx)$': require.resolve('ts-jest'), + '^.+\\.(js|jsx|mjs)$': jsTransform, + '^.+\\.(ts|tsx)$': tsTransform, '^.+\\.(gql|graphql)$': require.resolve('./transforms/graphql.js'), }, transformIgnorePatterns: [], - setupFiles: [require.resolve('regenerator-runtime/runtime')], + setupFiles: useEsbuild + ? [] + : [require.resolve('regenerator-runtime/runtime')], // fixes: https://github.com/facebook/jest/issues/6766 testURL: 'http://localhost', }; diff --git a/packages/jest-preset/transforms/esbuild.js b/packages/jest-preset/transforms/esbuild.js new file mode 100644 index 000000000..a0c4d8e61 --- /dev/null +++ b/packages/jest-preset/transforms/esbuild.js @@ -0,0 +1,17 @@ +// eslint-disable-next-line node/no-extraneous-require +const { createTransformer } = require('esbuild-jest'); + +const transformer = createTransformer({ + sourcemap: true, +}); + +module.exports = { + process(content, filename, config, opts) { + content = content.replace( + /importComponent\s*\(\s*\(\)\s+=>\s+import\(\s*'([^']+)'\s*\)\s*\)/g, + "importComponent({ component: require('$1') })" + ); + + return transformer.process(content, filename, config, opts); + }, +}; From 56ad96e417d53e6c980a0e878c2e2489fb8708ba Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Thu, 4 Mar 2021 18:05:27 +0100 Subject: [PATCH 7/8] chore: rename files which use JSX syntax to have the .jsx extension --- ...ponent-loading.js.snap => import-component-loading.jsx.snap} | 0 ...omponent-mocked.js.snap => import-component-mocked.jsx.snap} | 0 ...import-component-loading.js => import-component-loading.jsx} | 0 .../{import-component-mocked.js => import-component-mocked.jsx} | 0 packages/spec/integration/hops/{index.js => index.jsx} | 0 packages/spec/integration/hops/{text.js => text.jsx} | 0 .../__tests__/{index.js => index.spec.jsx} | 0 .../typescript-unit-testing/{headline.js => headline.jsx} | 0 packages/template-graphql/src/{app.js => app.jsx} | 0 packages/template-graphql/src/home/{index.js => index.jsx} | 0 .../__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} | 0 .../src/home/spec/{index.spec.js => index.spec.jsx} | 0 packages/template-react/src/{app.js => app.jsx} | 0 packages/template-react/src/counter/{index.js => index.jsx} | 0 .../__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} | 0 .../src/counter/spec/{index.spec.js => index.spec.jsx} | 0 packages/template-react/src/home/{index.js => index.jsx} | 0 .../__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} | 0 .../src/home/spec/{index.spec.js => index.spec.jsx} | 0 packages/template-redux/src/{app.js => app.jsx} | 0 packages/template-redux/src/counter/{counter.js => counter.jsx} | 0 packages/template-redux/src/counter/{index.js => index.jsx} | 0 .../{counter.spec.js.snap => counter.spec.jsx.snap} | 0 .../__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} | 0 .../src/counter/spec/{counter.spec.js => counter.spec.jsx} | 0 .../src/counter/spec/{index.spec.js => index.spec.jsx} | 2 +- packages/template-redux/src/home/{index.js => index.jsx} | 0 .../__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} | 0 .../src/home/spec/{index.spec.js => index.spec.jsx} | 0 29 files changed, 1 insertion(+), 1 deletion(-) rename packages/spec/integration/hops/__tests__/__snapshots__/{import-component-loading.js.snap => import-component-loading.jsx.snap} (100%) rename packages/spec/integration/hops/__tests__/__snapshots__/{import-component-mocked.js.snap => import-component-mocked.jsx.snap} (100%) rename packages/spec/integration/hops/__tests__/{import-component-loading.js => import-component-loading.jsx} (100%) rename packages/spec/integration/hops/__tests__/{import-component-mocked.js => import-component-mocked.jsx} (100%) rename packages/spec/integration/hops/{index.js => index.jsx} (100%) rename packages/spec/integration/hops/{text.js => text.jsx} (100%) rename packages/spec/integration/typescript-unit-testing/__tests__/{index.js => index.spec.jsx} (100%) rename packages/spec/integration/typescript-unit-testing/{headline.js => headline.jsx} (100%) rename packages/template-graphql/src/{app.js => app.jsx} (100%) rename packages/template-graphql/src/home/{index.js => index.jsx} (100%) rename packages/template-graphql/src/home/spec/__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} (100%) rename packages/template-graphql/src/home/spec/{index.spec.js => index.spec.jsx} (100%) rename packages/template-react/src/{app.js => app.jsx} (100%) rename packages/template-react/src/counter/{index.js => index.jsx} (100%) rename packages/template-react/src/counter/spec/__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} (100%) rename packages/template-react/src/counter/spec/{index.spec.js => index.spec.jsx} (100%) rename packages/template-react/src/home/{index.js => index.jsx} (100%) rename packages/template-react/src/home/spec/__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} (100%) rename packages/template-react/src/home/spec/{index.spec.js => index.spec.jsx} (100%) rename packages/template-redux/src/{app.js => app.jsx} (100%) rename packages/template-redux/src/counter/{counter.js => counter.jsx} (100%) rename packages/template-redux/src/counter/{index.js => index.jsx} (100%) rename packages/template-redux/src/counter/spec/__snapshots__/{counter.spec.js.snap => counter.spec.jsx.snap} (100%) rename packages/template-redux/src/counter/spec/__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} (100%) rename packages/template-redux/src/counter/spec/{counter.spec.js => counter.spec.jsx} (100%) rename packages/template-redux/src/counter/spec/{index.spec.js => index.spec.jsx} (95%) rename packages/template-redux/src/home/{index.js => index.jsx} (100%) rename packages/template-redux/src/home/spec/__snapshots__/{index.spec.js.snap => index.spec.jsx.snap} (100%) rename packages/template-redux/src/home/spec/{index.spec.js => index.spec.jsx} (100%) diff --git a/packages/spec/integration/hops/__tests__/__snapshots__/import-component-loading.js.snap b/packages/spec/integration/hops/__tests__/__snapshots__/import-component-loading.jsx.snap similarity index 100% rename from packages/spec/integration/hops/__tests__/__snapshots__/import-component-loading.js.snap rename to packages/spec/integration/hops/__tests__/__snapshots__/import-component-loading.jsx.snap diff --git a/packages/spec/integration/hops/__tests__/__snapshots__/import-component-mocked.js.snap b/packages/spec/integration/hops/__tests__/__snapshots__/import-component-mocked.jsx.snap similarity index 100% rename from packages/spec/integration/hops/__tests__/__snapshots__/import-component-mocked.js.snap rename to packages/spec/integration/hops/__tests__/__snapshots__/import-component-mocked.jsx.snap diff --git a/packages/spec/integration/hops/__tests__/import-component-loading.js b/packages/spec/integration/hops/__tests__/import-component-loading.jsx similarity index 100% rename from packages/spec/integration/hops/__tests__/import-component-loading.js rename to packages/spec/integration/hops/__tests__/import-component-loading.jsx diff --git a/packages/spec/integration/hops/__tests__/import-component-mocked.js b/packages/spec/integration/hops/__tests__/import-component-mocked.jsx similarity index 100% rename from packages/spec/integration/hops/__tests__/import-component-mocked.js rename to packages/spec/integration/hops/__tests__/import-component-mocked.jsx diff --git a/packages/spec/integration/hops/index.js b/packages/spec/integration/hops/index.jsx similarity index 100% rename from packages/spec/integration/hops/index.js rename to packages/spec/integration/hops/index.jsx diff --git a/packages/spec/integration/hops/text.js b/packages/spec/integration/hops/text.jsx similarity index 100% rename from packages/spec/integration/hops/text.js rename to packages/spec/integration/hops/text.jsx diff --git a/packages/spec/integration/typescript-unit-testing/__tests__/index.js b/packages/spec/integration/typescript-unit-testing/__tests__/index.spec.jsx similarity index 100% rename from packages/spec/integration/typescript-unit-testing/__tests__/index.js rename to packages/spec/integration/typescript-unit-testing/__tests__/index.spec.jsx diff --git a/packages/spec/integration/typescript-unit-testing/headline.js b/packages/spec/integration/typescript-unit-testing/headline.jsx similarity index 100% rename from packages/spec/integration/typescript-unit-testing/headline.js rename to packages/spec/integration/typescript-unit-testing/headline.jsx diff --git a/packages/template-graphql/src/app.js b/packages/template-graphql/src/app.jsx similarity index 100% rename from packages/template-graphql/src/app.js rename to packages/template-graphql/src/app.jsx diff --git a/packages/template-graphql/src/home/index.js b/packages/template-graphql/src/home/index.jsx similarity index 100% rename from packages/template-graphql/src/home/index.js rename to packages/template-graphql/src/home/index.jsx diff --git a/packages/template-graphql/src/home/spec/__snapshots__/index.spec.js.snap b/packages/template-graphql/src/home/spec/__snapshots__/index.spec.jsx.snap similarity index 100% rename from packages/template-graphql/src/home/spec/__snapshots__/index.spec.js.snap rename to packages/template-graphql/src/home/spec/__snapshots__/index.spec.jsx.snap diff --git a/packages/template-graphql/src/home/spec/index.spec.js b/packages/template-graphql/src/home/spec/index.spec.jsx similarity index 100% rename from packages/template-graphql/src/home/spec/index.spec.js rename to packages/template-graphql/src/home/spec/index.spec.jsx diff --git a/packages/template-react/src/app.js b/packages/template-react/src/app.jsx similarity index 100% rename from packages/template-react/src/app.js rename to packages/template-react/src/app.jsx diff --git a/packages/template-react/src/counter/index.js b/packages/template-react/src/counter/index.jsx similarity index 100% rename from packages/template-react/src/counter/index.js rename to packages/template-react/src/counter/index.jsx diff --git a/packages/template-react/src/counter/spec/__snapshots__/index.spec.js.snap b/packages/template-react/src/counter/spec/__snapshots__/index.spec.jsx.snap similarity index 100% rename from packages/template-react/src/counter/spec/__snapshots__/index.spec.js.snap rename to packages/template-react/src/counter/spec/__snapshots__/index.spec.jsx.snap diff --git a/packages/template-react/src/counter/spec/index.spec.js b/packages/template-react/src/counter/spec/index.spec.jsx similarity index 100% rename from packages/template-react/src/counter/spec/index.spec.js rename to packages/template-react/src/counter/spec/index.spec.jsx diff --git a/packages/template-react/src/home/index.js b/packages/template-react/src/home/index.jsx similarity index 100% rename from packages/template-react/src/home/index.js rename to packages/template-react/src/home/index.jsx diff --git a/packages/template-react/src/home/spec/__snapshots__/index.spec.js.snap b/packages/template-react/src/home/spec/__snapshots__/index.spec.jsx.snap similarity index 100% rename from packages/template-react/src/home/spec/__snapshots__/index.spec.js.snap rename to packages/template-react/src/home/spec/__snapshots__/index.spec.jsx.snap diff --git a/packages/template-react/src/home/spec/index.spec.js b/packages/template-react/src/home/spec/index.spec.jsx similarity index 100% rename from packages/template-react/src/home/spec/index.spec.js rename to packages/template-react/src/home/spec/index.spec.jsx diff --git a/packages/template-redux/src/app.js b/packages/template-redux/src/app.jsx similarity index 100% rename from packages/template-redux/src/app.js rename to packages/template-redux/src/app.jsx diff --git a/packages/template-redux/src/counter/counter.js b/packages/template-redux/src/counter/counter.jsx similarity index 100% rename from packages/template-redux/src/counter/counter.js rename to packages/template-redux/src/counter/counter.jsx diff --git a/packages/template-redux/src/counter/index.js b/packages/template-redux/src/counter/index.jsx similarity index 100% rename from packages/template-redux/src/counter/index.js rename to packages/template-redux/src/counter/index.jsx diff --git a/packages/template-redux/src/counter/spec/__snapshots__/counter.spec.js.snap b/packages/template-redux/src/counter/spec/__snapshots__/counter.spec.jsx.snap similarity index 100% rename from packages/template-redux/src/counter/spec/__snapshots__/counter.spec.js.snap rename to packages/template-redux/src/counter/spec/__snapshots__/counter.spec.jsx.snap diff --git a/packages/template-redux/src/counter/spec/__snapshots__/index.spec.js.snap b/packages/template-redux/src/counter/spec/__snapshots__/index.spec.jsx.snap similarity index 100% rename from packages/template-redux/src/counter/spec/__snapshots__/index.spec.js.snap rename to packages/template-redux/src/counter/spec/__snapshots__/index.spec.jsx.snap diff --git a/packages/template-redux/src/counter/spec/counter.spec.js b/packages/template-redux/src/counter/spec/counter.spec.jsx similarity index 100% rename from packages/template-redux/src/counter/spec/counter.spec.js rename to packages/template-redux/src/counter/spec/counter.spec.jsx diff --git a/packages/template-redux/src/counter/spec/index.spec.js b/packages/template-redux/src/counter/spec/index.spec.jsx similarity index 95% rename from packages/template-redux/src/counter/spec/index.spec.js rename to packages/template-redux/src/counter/spec/index.spec.jsx index 878499b04..69e081dd8 100644 --- a/packages/template-redux/src/counter/spec/index.spec.js +++ b/packages/template-redux/src/counter/spec/index.spec.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; import renderer from 'react-test-renderer'; import CounterContainer, { mapStateToProps } from '../'; diff --git a/packages/template-redux/src/home/index.js b/packages/template-redux/src/home/index.jsx similarity index 100% rename from packages/template-redux/src/home/index.js rename to packages/template-redux/src/home/index.jsx diff --git a/packages/template-redux/src/home/spec/__snapshots__/index.spec.js.snap b/packages/template-redux/src/home/spec/__snapshots__/index.spec.jsx.snap similarity index 100% rename from packages/template-redux/src/home/spec/__snapshots__/index.spec.js.snap rename to packages/template-redux/src/home/spec/__snapshots__/index.spec.jsx.snap diff --git a/packages/template-redux/src/home/spec/index.spec.js b/packages/template-redux/src/home/spec/index.spec.jsx similarity index 100% rename from packages/template-redux/src/home/spec/index.spec.js rename to packages/template-redux/src/home/spec/index.spec.jsx From f8f1ad37f2d0993be9cccb08f8efd905c79f5f76 Mon Sep 17 00:00:00 2001 From: Jonas Holland Date: Wed, 24 Mar 2021 13:49:16 +0100 Subject: [PATCH 8/8] chore: add esbuild example project --- package.json | 3 ++ .../esbuild-typescript/__tests__/develop.js | 28 ++++++++++++ .../esbuild-typescript/content.tsx | 3 ++ .../esbuild-typescript/headline.js | 5 +++ .../integration/esbuild-typescript/index.tsx | 17 +++++++ .../esbuild-typescript/package.json | 32 ++++++++++++++ .../esbuild-typescript/tsconfig.json | 3 ++ yarn.lock | 44 +++++++++++++++++-- 8 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 packages/spec/integration/esbuild-typescript/__tests__/develop.js create mode 100644 packages/spec/integration/esbuild-typescript/content.tsx create mode 100644 packages/spec/integration/esbuild-typescript/headline.js create mode 100644 packages/spec/integration/esbuild-typescript/index.tsx create mode 100644 packages/spec/integration/esbuild-typescript/package.json create mode 100644 packages/spec/integration/esbuild-typescript/tsconfig.json diff --git a/package.json b/package.json index 642b96695..2c479a8db 100644 --- a/package.json +++ b/package.json @@ -205,6 +205,9 @@ "babel-eslint": "^10.0.3", "canarist": "^2.2.2", "cz-conventional-changelog": "^3.0.2", + "esbuild": "^0.9.6", + "esbuild-jest": "^0.5.0", + "esbuild-loader": "^2.10.0", "eslint": "^7.0.0", "eslint-config-prettier": "^8.0.0", "eslint-plugin-import": "^2.18.2", diff --git a/packages/spec/integration/esbuild-typescript/__tests__/develop.js b/packages/spec/integration/esbuild-typescript/__tests__/develop.js new file mode 100644 index 000000000..862870a58 --- /dev/null +++ b/packages/spec/integration/esbuild-typescript/__tests__/develop.js @@ -0,0 +1,28 @@ +const { handleConsoleOutput } = require('../../../helpers'); + +describe('typescript development server', () => { + let url; + + beforeAll(async () => { + const { getUrl } = HopsCLI.start('--fast-dev', '--experimental-esbuild'); + url = await getUrl(); + }); + + it('renders a simple jsx site', async () => { + const { page } = await createPage(); + page.on('console', (msg) => handleConsoleOutput(msg)); + await page.goto(url); + expect(await page.content()).toMatch('

test

'); + + await page.close(); + }); + + it('supports code-splitting', async () => { + const { page } = await createPage(); + page.on('console', (msg) => handleConsoleOutput(msg)); + await page.goto(url); + expect(await page.content()).toMatch('

lorem ipsum.

'); + + await page.close(); + }); +}); diff --git a/packages/spec/integration/esbuild-typescript/content.tsx b/packages/spec/integration/esbuild-typescript/content.tsx new file mode 100644 index 000000000..f65842c38 --- /dev/null +++ b/packages/spec/integration/esbuild-typescript/content.tsx @@ -0,0 +1,3 @@ +import * as React from 'react'; + +export default () =>

lorem ipsum.

; diff --git a/packages/spec/integration/esbuild-typescript/headline.js b/packages/spec/integration/esbuild-typescript/headline.js new file mode 100644 index 000000000..643ea7c90 --- /dev/null +++ b/packages/spec/integration/esbuild-typescript/headline.js @@ -0,0 +1,5 @@ +import React from 'react'; + +const Headline = () =>

test

; + +export default Headline; diff --git a/packages/spec/integration/esbuild-typescript/index.tsx b/packages/spec/integration/esbuild-typescript/index.tsx new file mode 100644 index 000000000..f454a89cf --- /dev/null +++ b/packages/spec/integration/esbuild-typescript/index.tsx @@ -0,0 +1,17 @@ +import { render, importComponent } from 'hops'; +import * as React from 'react'; +import { Helmet } from 'react-helmet-async'; + +import Headline from './headline'; + +const Content = importComponent(() => import('./content')); + +export default render( + <> + + + + + + +); diff --git a/packages/spec/integration/esbuild-typescript/package.json b/packages/spec/integration/esbuild-typescript/package.json new file mode 100644 index 000000000..5739b307b --- /dev/null +++ b/packages/spec/integration/esbuild-typescript/package.json @@ -0,0 +1,32 @@ +{ + "name": "fixture-esbuild-typescript", + "version": "1.0.0", + "private": true, + "engines": { + "node": "12 || 14 || 15" + }, + "jest": { + "displayName": "integration", + "testEnvironment": "jest-environment-hops", + "setupFilesAfterEnv": [ + "../../jest.setup.js" + ] + }, + "hops": { + "gracePeriod": 0 + }, + "scripts": { + "start": "hops start --experimental-esbuild", + "build": "hops build --experimental-esbuild" + }, + "dependencies": { + "esbuild": "*", + "esbuild-jest": "*", + "esbuild-loader": "*", + "hops": "*", + "hops-typescript": "*", + "react": "*", + "react-helmet-async": "*", + "typescript": "*" + } +} diff --git a/packages/spec/integration/esbuild-typescript/tsconfig.json b/packages/spec/integration/esbuild-typescript/tsconfig.json new file mode 100644 index 000000000..975acf3e3 --- /dev/null +++ b/packages/spec/integration/esbuild-typescript/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "hops-typescript/tsconfig.json" +} diff --git a/yarn.lock b/yarn.lock index 832918c3a..0d09e3032 100644 --- a/yarn.lock +++ b/yarn.lock @@ -142,7 +142,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.11.tgz#9c8fe523c206979c9a81b1e12fe50c1254f1aa35" integrity sha512-BwKEkO+2a67DcFeS3RLl0Z3Gs2OvdXewuWjc1Hfokhb5eQWP9YRYH1/+VrVZvql2CfjOiNGqSAFOYt4lsqTHzg== -"@babel/core@^7.1.0", "@babel/core@^7.7.5", "@babel/core@^7.9.0": +"@babel/core@^7.1.0", "@babel/core@^7.12.17", "@babel/core@^7.7.5", "@babel/core@^7.9.0": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.10.tgz#07de050bbd8193fcd8a3c27918c0890613a94559" integrity sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw== @@ -733,7 +733,7 @@ "@babel/helper-plugin-utils" "^7.13.0" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.13.8": +"@babel/plugin-transform-modules-commonjs@^7.12.13", "@babel/plugin-transform-modules-commonjs@^7.13.8": version "7.13.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz#7b01ad7c2dcf2275b06fa1781e00d13d420b3e1b" integrity sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw== @@ -5989,6 +5989,32 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild-jest@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/esbuild-jest/-/esbuild-jest-0.5.0.tgz#7a9964bfdecafca3b675a8aeb08193bcdba8b9d7" + integrity sha512-AMZZCdEpXfNVOIDvURlqYyHwC8qC1/BFjgsrOiSL1eyiIArVtHL8YAC83Shhn16cYYoAWEW17yZn0W/RJKJKHQ== + dependencies: + "@babel/core" "^7.12.17" + "@babel/plugin-transform-modules-commonjs" "^7.12.13" + babel-jest "^26.6.3" + +esbuild-loader@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.10.0.tgz#35b570187aee0036b2f4b37db66870f7407f3d40" + integrity sha512-BRWmc/7gU6/FmI+MP+E+9Zb/CE0BA1XMOQkdvJ7B/T2gad1Mlim8aMhvvRdS9on5S8JzkC+uNHGQmt/WmbbXbQ== + dependencies: + esbuild "^0.9.2" + joycon "^2.2.5" + json5 "^2.2.0" + loader-utils "^2.0.0" + type-fest "^0.21.3" + webpack-sources "^2.2.0" + +esbuild@^0.9.2, esbuild@^0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.9.6.tgz#2cae519e7ce2328ecf57ae738090d07ce7245850" + integrity sha512-F6vASxU0wT/Davt9aj2qtDwDNSkQxh9VbyO56M7PDWD+D/Vgq/rmUDGDQo7te76W5auauVojjnQr/wTu3vpaUA== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -8617,6 +8643,11 @@ jmespath@0.15.0: resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= +joycon@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" + integrity sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -8717,7 +8748,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@2.x, json5@^2.1.2: +json5@2.x, json5@^2.1.2, json5@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== @@ -13716,6 +13747,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" @@ -14174,7 +14210,7 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack- source-list-map "^2.0.0" source-map "~0.6.1" -webpack-sources@^2.0.0: +webpack-sources@^2.0.0, webpack-sources@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac" integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==