From c2c29e832e6ff875bd8be7025b3337249ee2afdb Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Fri, 17 Apr 2026 12:02:59 +0300 Subject: [PATCH 01/11] refactor(template): generate a template with less empty lines --- .../templates/init/default/webpack.config.tpl | 16 ++++------ ...bpack.config.js.tpl => webpack.config.tpl} | 30 ++++++------------- ...bpack.config.js.tpl => webpack.config.tpl} | 30 ++++++------------- ...bpack.config.js.tpl => webpack.config.tpl} | 0 4 files changed, 23 insertions(+), 53 deletions(-) rename packages/create-webpack-app/templates/init/react/{webpack.config.js.tpl => webpack.config.tpl} (83%) rename packages/create-webpack-app/templates/init/svelte/{webpack.config.js.tpl => webpack.config.tpl} (85%) rename packages/create-webpack-app/templates/init/vue/{webpack.config.js.tpl => webpack.config.tpl} (100%) diff --git a/packages/create-webpack-app/templates/init/default/webpack.config.tpl b/packages/create-webpack-app/templates/init/default/webpack.config.tpl index 7eaed3b1263..339e0bf2b6f 100644 --- a/packages/create-webpack-app/templates/init/default/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/default/webpack.config.tpl @@ -10,13 +10,9 @@ import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const isProduction = process.env.NODE_ENV === "production"; -<% if (cssType !== "none") { %> -<% if (extractPlugin === "Yes") { %> -const stylesHandler = MiniCssExtractPlugin.loader; -<% } else if (extractPlugin === "Only for Production") { %> -const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; -<% } else { %> +const isProduction = process.env.NODE_ENV === "production";<% if (cssType !== "none") { %><% if (extractPlugin === "Yes") { %> +const stylesHandler = MiniCssExtractPlugin.loader;<% } else if (extractPlugin === "Only for Production") { %> +const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader";<% } else { %> const stylesHandler = "style-loader";<% } %><% } %> /** @type {import("webpack").Configuration} */ @@ -31,10 +27,8 @@ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ template: "index.html", - }), -<% } %><% if (extractPlugin === "Yes") { %> - new MiniCssExtractPlugin(), -<% } %> + }),<% } %><% if (extractPlugin === "Yes") { %> + new MiniCssExtractPlugin(),<% } %> // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], diff --git a/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/react/webpack.config.tpl similarity index 83% rename from packages/create-webpack-app/templates/init/react/webpack.config.js.tpl rename to packages/create-webpack-app/templates/init/react/webpack.config.tpl index cf6ce755bf9..7cce2e81afe 100644 --- a/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/react/webpack.config.tpl @@ -8,16 +8,10 @@ import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const isProduction = process.env.NODE_ENV === "production"; -<% if (cssType !== "none") { %> -<% if (extractPlugin === "Yes") { %> -const stylesHandler = MiniCssExtractPlugin.loader; -<% } else if (extractPlugin === "Only for Production") { %> -const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; -<% } else { %> -const stylesHandler = "style-loader"; -<% } %> -<% } %> +const isProduction = process.env.NODE_ENV === "production";<% if (cssType !== "none") { %><% if (extractPlugin === "Yes") { %> +const stylesHandler = MiniCssExtractPlugin.loader;<% } else if (extractPlugin === "Only for Production") { %> +const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader";<% } else { %> +const stylesHandler = "style-loader";<% } %><% } %> /** @type {import("webpack").Configuration} */ const config = { @@ -31,10 +25,8 @@ const config = { plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ template: "index.html", - }), -<% } %><% if (extractPlugin === "Yes") { %> - new MiniCssExtractPlugin(), -<% } %> + }),<% } %><% if (extractPlugin === "Yes") { %> + new MiniCssExtractPlugin(),<% } %> // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -94,13 +86,9 @@ const config = { export default () => { if (isProduction) { - config.mode = "production"; - <% if (extractPlugin === "Only for Production") { %> - config.plugins.push(new MiniCssExtractPlugin()); - <% } %> - <% if (workboxWebpackPlugin) { %> - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); - <% } %> + config.mode = "production";<% if (extractPlugin === "Only for Production") { %> + config.plugins.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> + config.plugins.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> } else { config.mode = "development"; } diff --git a/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl similarity index 85% rename from packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl rename to packages/create-webpack-app/templates/init/svelte/webpack.config.tpl index 86bd7bdecbe..72dcdef181f 100644 --- a/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl @@ -8,16 +8,10 @@ import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const isProduction = process.env.NODE_ENV === "production"; -<% if (cssType !== "none") { %> -<% if (extractPlugin === "Yes") { %> -const stylesHandler = MiniCssExtractPlugin.loader; -<% } else if (extractPlugin === "Only for Production") { %> -const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; -<% } else { %> -const stylesHandler = "style-loader"; -<% } %> -<% } %> +const isProduction = process.env.NODE_ENV === "production";<% if (cssType !== "none") { %><% if (extractPlugin === "Yes") { %> +const stylesHandler = MiniCssExtractPlugin.loader;<% } else if (extractPlugin === "Only for Production") { %> +const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader";<% } else { %> +const stylesHandler = "style-loader";<% } %><% } %> /** @type {import("webpack").Configuration} */ const config = { @@ -31,10 +25,8 @@ const config = { plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ template: "./index.html", - }), -<% } %><% if (extractPlugin === "Yes") { %> - new MiniCssExtractPlugin(), -<% } %> + }),<% } %><% if (extractPlugin === "Yes") { %> + new MiniCssExtractPlugin(),<% } %> // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -108,13 +100,9 @@ const config = { export default () => { if (isProduction) { - config.mode = "production"; - <% if (extractPlugin === "Only for Production") { %> - config.plugins.push(new MiniCssExtractPlugin()); - <% } %> - <% if (workboxWebpackPlugin) { %> - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); - <% } %> + config.mode = "production";<% if (extractPlugin === "Only for Production") { %> + config.plugins.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> + config.plugins.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> } else { config.mode = "development"; } diff --git a/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl similarity index 100% rename from packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl rename to packages/create-webpack-app/templates/init/vue/webpack.config.tpl From 501dd337fac74f38584ce992a43f7b3047b8f3bd Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Fri, 17 Apr 2026 12:09:31 +0300 Subject: [PATCH 02/11] fix(typescript): generate a webpack.config.ts instead of js one --- packages/create-webpack-app/src/generators/init/react.ts | 9 +++++++-- .../create-webpack-app/src/generators/init/svelte.ts | 9 +++++++-- packages/create-webpack-app/src/generators/init/vue.ts | 9 +++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/create-webpack-app/src/generators/init/react.ts b/packages/create-webpack-app/src/generators/init/react.ts index 8b7db38a606..188139d3270 100644 --- a/packages/create-webpack-app/src/generators/init/react.ts +++ b/packages/create-webpack-app/src/generators/init/react.ts @@ -151,7 +151,10 @@ export default async function reactInitGenerator(plop: NodePlopAPI) { const files: FileRecord[] = [ { filePath: "./index.html", fileType: "text" }, - { filePath: "webpack.config.js", fileType: "text" }, + { + filePath: answers.langType === "Typescript" ? "webpack.config.ts" : "webpack.config.js", + fileType: "text", + }, { filePath: "package.json", fileType: "text" }, { filePath: "README.md", fileType: "text" }, { filePath: "./src/assets/webpack.png", fileType: "binary" }, @@ -206,7 +209,9 @@ export default async function reactInitGenerator(plop: NodePlopAPI) { templateFile: join( plop.getPlopfilePath(), "../templates/init/react", - `${file.filePath}.tpl`, + file.filePath.startsWith("webpack.config") + ? "webpack.config.tpl" + : `${file.filePath}.tpl`, ), fileType: file.fileType, data: answers, diff --git a/packages/create-webpack-app/src/generators/init/svelte.ts b/packages/create-webpack-app/src/generators/init/svelte.ts index f81ff031329..08c6403efff 100644 --- a/packages/create-webpack-app/src/generators/init/svelte.ts +++ b/packages/create-webpack-app/src/generators/init/svelte.ts @@ -143,7 +143,10 @@ export default async function svelteInitGenerator(plop: NodePlopAPI) { const files: FileRecord[] = [ { filePath: "./index.html", fileType: "text" }, { filePath: "./src/assets/webpack.png", fileType: "binary" }, - { filePath: "webpack.config.js", fileType: "text" }, + { + filePath: answers.langType === "Typescript" ? "webpack.config.ts" : "webpack.config.js", + fileType: "text", + }, { filePath: "package.json", fileType: "text" }, { filePath: "README.md", fileType: "text" }, { filePath: "./src/components/HelloWorld.svelte", fileType: "text" }, @@ -193,7 +196,9 @@ export default async function svelteInitGenerator(plop: NodePlopAPI) { templateFile: join( plop.getPlopfilePath(), "../templates/init/svelte", - `${file.filePath}.tpl`, + file.filePath.startsWith("webpack.config") + ? "webpack.config.tpl" + : `${file.filePath}.tpl`, ), fileType: file.fileType, data: answers, diff --git a/packages/create-webpack-app/src/generators/init/vue.ts b/packages/create-webpack-app/src/generators/init/vue.ts index 793e5889a82..fe105558cfc 100644 --- a/packages/create-webpack-app/src/generators/init/vue.ts +++ b/packages/create-webpack-app/src/generators/init/vue.ts @@ -155,7 +155,10 @@ export default async function vueInitGenerator(plop: NodePlopAPI) { const files: FileRecord[] = [ { filePath: "./index.html", fileType: "text" }, { filePath: "./src/assets/webpack.png", fileType: "binary" }, - { filePath: "webpack.config.js", fileType: "text" }, + { + filePath: answers.langType === "Typescript" ? "webpack.config.ts" : "webpack.config.js", + fileType: "text", + }, { filePath: "package.json", fileType: "text" }, { filePath: "README.md", fileType: "text" }, { filePath: "./src/App.vue", fileType: "text" }, @@ -215,7 +218,9 @@ export default async function vueInitGenerator(plop: NodePlopAPI) { templateFile: join( plop.getPlopfilePath(), "../templates/init/vue", - `${file.filePath}.tpl`, + file.filePath.startsWith("webpack.config") + ? "webpack.config.tpl" + : `${file.filePath}.tpl`, ), fileType: file.fileType, data: answers, From 4604c7db80be40638bf113396ff851c26f6ec786 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Fri, 17 Apr 2026 12:22:40 +0300 Subject: [PATCH 03/11] fix(template): add necessary types for typescript case --- .../templates/init/react/webpack.config.tpl | 4 +++- .../templates/init/svelte/webpack.config.tpl | 4 +++- .../create-webpack-app/templates/init/vue/webpack.config.tpl | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/create-webpack-app/templates/init/react/webpack.config.tpl b/packages/create-webpack-app/templates/init/react/webpack.config.tpl index 7cce2e81afe..125089a4712 100644 --- a/packages/create-webpack-app/templates/init/react/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/react/webpack.config.tpl @@ -2,6 +2,8 @@ import path from "node:path"; import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> +import { type Configuration } from "webpack";<% if (devServer) { %> +import "webpack-dev-server";<% } %><% } %><% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> @@ -14,7 +16,7 @@ const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader const stylesHandler = "style-loader";<% } %><% } %> /** @type {import("webpack").Configuration} */ -const config = { +const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { entry: "<%= entry %>", output: { path: path.resolve(__dirname, "dist"), diff --git a/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl index 72dcdef181f..a141cef697e 100644 --- a/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl @@ -2,6 +2,8 @@ import path from "node:path"; import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> +import { type Configuration } from "webpack";<% if (devServer) { %> +import "webpack-dev-server";<% } %><% } %><% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> @@ -14,7 +16,7 @@ const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader const stylesHandler = "style-loader";<% } %><% } %> /** @type {import("webpack").Configuration} */ -const config = { +const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { entry: "<%= entry %>", output: { path: path.resolve(__dirname, "dist"), diff --git a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl index d4cdf176634..8039287c4f0 100644 --- a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl @@ -3,6 +3,8 @@ import { VueLoaderPlugin } from "vue-loader"; import path from "node:path"; import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> +import { type Configuration } from "webpack";<% if (devServer) { %> +import "webpack-dev-server";<% } %><% } %><% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> @@ -21,7 +23,7 @@ const stylesHandler = "vue-style-loader"; <% } %> /** @type {import("webpack").Configuration} */ -const config = { +const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { entry: "<%= entry %>", output: { path: path.resolve(__dirname, "dist"), From a16bcca50dbf3996b16c9b65050b1da6e9a893f4 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Fri, 17 Apr 2026 12:34:37 +0300 Subject: [PATCH 04/11] refactor(template): generate a template with less empty lines --- .../templates/init/vue/webpack.config.tpl | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl index 8039287c4f0..b0c027c3b03 100644 --- a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl @@ -11,16 +11,10 @@ import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const isProduction = process.env.NODE_ENV === "production"; -<% if (cssType !== "none") { %> -<% if (extractPlugin === "Yes") { %> -const stylesHandler = MiniCssExtractPlugin.loader; -<% } else if (extractPlugin === "Only for Production") { %> -const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader"; -<% } else { %> -const stylesHandler = "vue-style-loader"; -<% } %> -<% } %> +const isProduction = process.env.NODE_ENV === "production";<% if (cssType !== "none") { %><% if (extractPlugin === "Yes") { %> +const stylesHandler = MiniCssExtractPlugin.loader;<% } else if (extractPlugin === "Only for Production") { %> +const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader";<% } else { %> +const stylesHandler = "vue-style-loader";<% } %><% } %> /** @type {import("webpack").Configuration} */ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { @@ -35,10 +29,8 @@ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { new VueLoaderPlugin(),<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ template: "index.html", - }), -<% } %><% if (extractPlugin === "Yes") { %> - new MiniCssExtractPlugin(), -<% } %> + }),<% } %><% if (extractPlugin === "Yes") { %> + new MiniCssExtractPlugin(),<% } %> // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -105,13 +97,9 @@ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { export default () => { if (isProduction) { - config.mode = "production"; - <% if (extractPlugin === "Only for Production") { %> - config.plugins.push(new MiniCssExtractPlugin()); - <% } %> - <% if (workboxWebpackPlugin) { %> - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); - <% } %> + config.mode = "production";<% if (extractPlugin === "Only for Production") { %> + config.plugins.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> + config.plugins.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> } else { config.mode = "development"; } From e67d896d689cffa4b0f8e1e80e93e84917198d75 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Fri, 17 Apr 2026 13:06:23 +0300 Subject: [PATCH 05/11] refactor(template): modernize tsconfig for frameworks --- .../templates/init/react/tsconfig.json.tpl | 11 +++++++---- .../templates/init/svelte/tsconfig.json.tpl | 10 +++++++--- .../templates/init/vue/tsconfig.json.tpl | 11 ++++++++--- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/create-webpack-app/templates/init/react/tsconfig.json.tpl b/packages/create-webpack-app/templates/init/react/tsconfig.json.tpl index 37b8169e222..9972c80205c 100644 --- a/packages/create-webpack-app/templates/init/react/tsconfig.json.tpl +++ b/packages/create-webpack-app/templates/init/react/tsconfig.json.tpl @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "esnext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, @@ -10,11 +10,14 @@ "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "react-jsx" + "jsx": "react-jsx", + "verbatimModuleSyntax": true, + "erasableSyntaxOnly": true, + "rewriteRelativeImportExtensions": true, }, "include": ["src/**/*", "index.d.ts"], "exclude": ["node_modules", "dist"] -} +} \ No newline at end of file diff --git a/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl b/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl index 40932dd52a0..8299959a98b 100644 --- a/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl +++ b/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl @@ -1,14 +1,18 @@ { "extends": "@tsconfig/svelte/tsconfig.json", "compilerOptions": { - "target": "es5", - "module": "es6", + "target": "esnext", + "module": "esnext", "strict": true, - "moduleResolution": "node", + "moduleResolution": "bundler", "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, + "verbatimModuleSyntax": true, + "erasableSyntaxOnly": true, + "isolatedModules": true, + "rewriteRelativeImportExtensions": true, }, "include": [ "src/**/*.ts", diff --git a/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl b/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl index 5a61545c28b..8d872da9c9d 100644 --- a/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl +++ b/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl @@ -1,15 +1,19 @@ { "compilerOptions": { - "target": "es5", - "module": "es6", + "target": "esnext", + "module": "esnext", "strict": true, "jsx": "preserve", - "moduleResolution": "node", + "moduleResolution": "bundler", "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, "baseUrl": ".", + "verbatimModuleSyntax": true, + "erasableSyntaxOnly": true, + "isolatedModules": true, + "rewriteRelativeImportExtensions": true, "types": [ "webpack-env", "vue-router" @@ -22,6 +26,7 @@ "lib": [ "esnext", "dom", + "dom.iterable", ] }, "include": [ From 93dc8b264fc043b7b055441c34cf4a7150e635f2 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Fri, 17 Apr 2026 22:49:54 +0300 Subject: [PATCH 06/11] fix(template): remove depreacated config & fix possible undefined type --- .../templates/init/default/webpack.config.tpl | 4 ++-- .../templates/init/react/webpack.config.tpl | 4 ++-- .../templates/init/svelte/webpack.config.tpl | 4 ++-- .../create-webpack-app/templates/init/vue/tsconfig.json.tpl | 1 - .../create-webpack-app/templates/init/vue/webpack.config.tpl | 4 ++-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/create-webpack-app/templates/init/default/webpack.config.tpl b/packages/create-webpack-app/templates/init/default/webpack.config.tpl index 339e0bf2b6f..a4da1add247 100644 --- a/packages/create-webpack-app/templates/init/default/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/default/webpack.config.tpl @@ -85,8 +85,8 @@ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { export default () => { if (isProduction) { config.mode = "production";<% if (extractPlugin === "Only for Production") { %> - config.plugins!.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> - config.plugins!.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> + config.plugins?.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> } else { config.mode = "development"; } diff --git a/packages/create-webpack-app/templates/init/react/webpack.config.tpl b/packages/create-webpack-app/templates/init/react/webpack.config.tpl index 125089a4712..ef08cb8ca2d 100644 --- a/packages/create-webpack-app/templates/init/react/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/react/webpack.config.tpl @@ -89,8 +89,8 @@ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { export default () => { if (isProduction) { config.mode = "production";<% if (extractPlugin === "Only for Production") { %> - config.plugins.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> + config.plugins?.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> } else { config.mode = "development"; } diff --git a/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl index a141cef697e..fda8631c31e 100644 --- a/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl @@ -103,8 +103,8 @@ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { export default () => { if (isProduction) { config.mode = "production";<% if (extractPlugin === "Only for Production") { %> - config.plugins.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> + config.plugins?.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> } else { config.mode = "development"; } diff --git a/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl b/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl index 8d872da9c9d..277b97be1b4 100644 --- a/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl +++ b/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl @@ -9,7 +9,6 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, - "baseUrl": ".", "verbatimModuleSyntax": true, "erasableSyntaxOnly": true, "isolatedModules": true, diff --git a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl index b0c027c3b03..a483d54a48a 100644 --- a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl @@ -98,8 +98,8 @@ const config <% if (langType === "Typescript") { %>: Configuration <% } %>= { export default () => { if (isProduction) { config.mode = "production";<% if (extractPlugin === "Only for Production") { %> - config.plugins.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> + config.plugins?.push(new MiniCssExtractPlugin());<% } %><% if (workboxWebpackPlugin) { %> + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW());<% } %> } else { config.mode = "development"; } From 006c1f8cb0a38512c17571068af0381ff7c9305e Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Fri, 17 Apr 2026 22:51:01 +0300 Subject: [PATCH 07/11] test(typescript): add typescript test case for all frameworks --- test/create-webpack-app/init/init.test.js | 72 +++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/test/create-webpack-app/init/init.test.js b/test/create-webpack-app/init/init.test.js index c8b946ca5dd..a16da1119b7 100644 --- a/test/create-webpack-app/init/init.test.js +++ b/test/create-webpack-app/init/init.test.js @@ -508,6 +508,30 @@ describe("create-webpack-app cli", () => { expect(readFromWebpackConfig(dir)).toMatchSnapshot(); }); + it("should generate react template with typescript", async () => { + const { stdout } = await runPromptWithAnswers( + dir, + ["init", ".", "--template=react"], + [`${DOWN}${ENTER}`, `y${ENTER}`, `y${ENTER}`, ENTER, `y${ENTER}`, ENTER, ENTER, ENTER], + ); + + expect(stdout).toContain("Project has been initialised with webpack!"); + expect(stdout).toContain("webpack.config.ts"); + + const files = [ + ...reactTemplateFiles.filter((file) => file !== "webpack.config.js"), + "webpack.config.ts", + "tsconfig.json", + ]; + + for (const file of files) { + expect(existsSync(resolve(dir, file))).toBeTruthy(); + } + + expect(readFromPkgJSON(dir)).toMatchSnapshot(); + expect(readFromWebpackConfig(dir, "webpack.config.ts")).toMatchSnapshot(); + }); + it("should generate vue template with store and router support on prompt answers", async () => { const { stdout } = await runPromptWithAnswers( dir, @@ -532,6 +556,30 @@ describe("create-webpack-app cli", () => { expect(readFromWebpackConfig(dir)).toMatchSnapshot(); }); + it("should generate vue template with typescript", async () => { + const { stdout } = await runPromptWithAnswers( + dir, + ["init", ".", "--template=vue"], + [`${DOWN}${ENTER}`, `y${ENTER}`, `y${ENTER}`, ENTER, `y${ENTER}`, ENTER, ENTER, ENTER], + ); + + expect(stdout).toContain("Project has been initialised with webpack!"); + expect(stdout).toContain("webpack.config.ts"); + + const files = [ + ...vueTemplateFiles.filter((file) => file !== "webpack.config.js"), + "webpack.config.ts", + "tsconfig.json", + ]; + + for (const file of files) { + expect(existsSync(resolve(dir, file))).toBeTruthy(); + } + + expect(readFromPkgJSON(dir)).toMatchSnapshot(); + expect(readFromWebpackConfig(dir, "webpack.config.ts")).toMatchSnapshot(); + }); + it("should generate svelte template with prompt answers", async () => { const { stdout } = await runPromptWithAnswers( dir, @@ -553,4 +601,28 @@ describe("create-webpack-app cli", () => { // Check if the generated webpack configuration matches the snapshot expect(readFromWebpackConfig(dir)).toMatchSnapshot(); }); + + it("should generate svelte template with typescript", async () => { + const { stdout } = await runPromptWithAnswers( + dir, + ["init", ".", "--template=svelte"], + [`${DOWN}${ENTER}`, `y${ENTER}`, `y${ENTER}`, ENTER, `y${ENTER}`, ENTER, ENTER, ENTER], + ); + + expect(stdout).toContain("Project has been initialised with webpack!"); + expect(stdout).toContain("webpack.config.ts"); + + const files = [ + ...svelteTemplateFiles.filter((file) => file !== "webpack.config.js"), + "webpack.config.ts", + "tsconfig.json", + ]; + + for (const file of files) { + expect(existsSync(resolve(dir, file))).toBeTruthy(); + } + + expect(readFromPkgJSON(dir)).toMatchSnapshot(); + expect(readFromWebpackConfig(dir, "webpack.config.ts")).toMatchSnapshot(); + }); }); From f0fd8bfb28995db68fe9b5f37fff0a4907ca5d13 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Sat, 18 Apr 2026 00:40:16 +0300 Subject: [PATCH 08/11] fix(template): set the conditional import depending on langtype --- .../create-webpack-app/templates/init/react/webpack.config.tpl | 2 +- .../create-webpack-app/templates/init/svelte/webpack.config.tpl | 2 +- .../create-webpack-app/templates/init/vue/webpack.config.tpl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-webpack-app/templates/init/react/webpack.config.tpl b/packages/create-webpack-app/templates/init/react/webpack.config.tpl index ef08cb8ca2d..4176f8df107 100644 --- a/packages/create-webpack-app/templates/init/react/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/react/webpack.config.tpl @@ -1,7 +1,7 @@ // Generated using webpack-cli https://github.com/webpack/webpack-cli import path from "node:path"; -import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> +import { fileURLToPath } from "node:url";<% if (langType === "Typescript") { %> import { type Configuration } from "webpack";<% if (devServer) { %> import "webpack-dev-server";<% } %><% } %><% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> diff --git a/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl index fda8631c31e..cc010d7d97c 100644 --- a/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/svelte/webpack.config.tpl @@ -1,7 +1,7 @@ // Generated using webpack-cli https://github.com/webpack/webpack-cli import path from "node:path"; -import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> +import { fileURLToPath } from "node:url";<% if (langType === "Typescript") { %> import { type Configuration } from "webpack";<% if (devServer) { %> import "webpack-dev-server";<% } %><% } %><% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> diff --git a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl index a483d54a48a..4be7e433154 100644 --- a/packages/create-webpack-app/templates/init/vue/webpack.config.tpl +++ b/packages/create-webpack-app/templates/init/vue/webpack.config.tpl @@ -2,7 +2,7 @@ import { VueLoaderPlugin } from "vue-loader"; import path from "node:path"; -import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> +import { fileURLToPath } from "node:url";<% if (langType === "Typescript") { %> import { type Configuration } from "webpack";<% if (devServer) { %> import "webpack-dev-server";<% } %><% } %><% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> From 6f80d5c48ddc3582c5299bf6f289c92a4a1fc8ee Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Sat, 18 Apr 2026 00:41:20 +0300 Subject: [PATCH 09/11] test(init): add typescript test suits for svelte, vue and react --- test/create-webpack-app/init/init.test.js | 53 +++++++++++++---------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/test/create-webpack-app/init/init.test.js b/test/create-webpack-app/init/init.test.js index a16da1119b7..1a59d4a1e0d 100644 --- a/test/create-webpack-app/init/init.test.js +++ b/test/create-webpack-app/init/init.test.js @@ -40,6 +40,31 @@ const svelteTemplateFiles = [ "src/store/index.js", ]; +const reactTypescriptTemplateFiles = [ + ...defaultTemplateFiles.slice(0, 3), + "src/index.tsx", + ...defaultTemplateFiles.slice(4).filter((file) => file !== "webpack.config.js"), + "webpack.config.ts", + "tsconfig.json", +]; + +const vueTypescriptTemplateFiles = [ + ...defaultTemplateFiles.slice(0, 3), + "src/main.ts", + ...defaultTemplateFiles.slice(4).filter((file) => file !== "webpack.config.js"), + "webpack.config.ts", + "tsconfig.json", +]; + +const svelteTypescriptTemplateFiles = [ + ...defaultTemplateFiles.slice(0, 3), + "src/main.ts", + ...defaultTemplateFiles.slice(4).filter((file) => file !== "webpack.config.js"), + "webpack.config.ts", + "tsconfig.json", + "src/store/index.ts", +]; + // helper function to resolve the path from the test directory to actual assets // Helper to read from package.json in a given path const readFromPkgJSON = (path) => { @@ -518,13 +543,7 @@ describe("create-webpack-app cli", () => { expect(stdout).toContain("Project has been initialised with webpack!"); expect(stdout).toContain("webpack.config.ts"); - const files = [ - ...reactTemplateFiles.filter((file) => file !== "webpack.config.js"), - "webpack.config.ts", - "tsconfig.json", - ]; - - for (const file of files) { + for (const file of reactTypescriptTemplateFiles) { expect(existsSync(resolve(dir, file))).toBeTruthy(); } @@ -560,19 +579,13 @@ describe("create-webpack-app cli", () => { const { stdout } = await runPromptWithAnswers( dir, ["init", ".", "--template=vue"], - [`${DOWN}${ENTER}`, `y${ENTER}`, `y${ENTER}`, ENTER, `y${ENTER}`, ENTER, ENTER, ENTER], + [`${DOWN}${ENTER}`, `y${ENTER}`, `y${ENTER}`, `${ENTER}`, `y${ENTER}`, ENTER, ENTER], ); expect(stdout).toContain("Project has been initialised with webpack!"); expect(stdout).toContain("webpack.config.ts"); - const files = [ - ...vueTemplateFiles.filter((file) => file !== "webpack.config.js"), - "webpack.config.ts", - "tsconfig.json", - ]; - - for (const file of files) { + for (const file of vueTypescriptTemplateFiles) { expect(existsSync(resolve(dir, file))).toBeTruthy(); } @@ -606,19 +619,13 @@ describe("create-webpack-app cli", () => { const { stdout } = await runPromptWithAnswers( dir, ["init", ".", "--template=svelte"], - [`${DOWN}${ENTER}`, `y${ENTER}`, `y${ENTER}`, ENTER, `y${ENTER}`, ENTER, ENTER, ENTER], + [`${DOWN}${ENTER}`, `y${ENTER}`, ENTER, `y${ENTER}`, ENTER, ENTER], ); expect(stdout).toContain("Project has been initialised with webpack!"); expect(stdout).toContain("webpack.config.ts"); - const files = [ - ...svelteTemplateFiles.filter((file) => file !== "webpack.config.js"), - "webpack.config.ts", - "tsconfig.json", - ]; - - for (const file of files) { + for (const file of svelteTypescriptTemplateFiles) { expect(existsSync(resolve(dir, file))).toBeTruthy(); } From 0c56ab2ead871b5e90050fbb56260fb0b0b03411 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Sat, 18 Apr 2026 00:43:12 +0300 Subject: [PATCH 10/11] test(init): update snapshots --- .../__snapshots__/init.test.js.snap.webpack5 | 425 +++++++++++++++--- 1 file changed, 361 insertions(+), 64 deletions(-) diff --git a/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 b/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 index 82dc02fa6f7..94c723a4fac 100644 --- a/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 +++ b/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 @@ -76,7 +76,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -146,7 +145,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -157,7 +155,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -223,7 +220,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -234,7 +230,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -259,7 +254,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new WorkboxWebpackPlugin.GenerateSW()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -299,7 +294,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -374,7 +368,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -388,7 +381,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -413,7 +405,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new WorkboxWebpackPlugin.GenerateSW()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -457,7 +449,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -471,7 +462,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -496,7 +486,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new WorkboxWebpackPlugin.GenerateSW()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -538,7 +528,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -552,7 +541,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -577,7 +565,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new WorkboxWebpackPlugin.GenerateSW()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -621,7 +609,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -635,7 +622,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -660,7 +646,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new WorkboxWebpackPlugin.GenerateSW()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -704,7 +690,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -718,7 +703,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -743,7 +727,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new WorkboxWebpackPlugin.GenerateSW()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -846,12 +830,8 @@ import WorkboxWebpackPlugin from "workbox-webpack-plugin"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - - const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; - - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.jsx", @@ -865,7 +845,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -905,12 +884,117 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - - config.plugins.push(new MiniCssExtractPlugin()); - - - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); - + config.plugins?.push(new MiniCssExtractPlugin()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); + } else { + config.mode = "development"; + } + return config; +}; +" +`; + +exports[`create-webpack-app cli should generate react template with typescript 1`] = ` +{ + "description": "My webpack project", + "devDependencies": { + "@types/react": "x.x.x", + "@types/react-dom": "x.x.x", + "@types/react-router-dom": "x.x.x", + "autoprefixer": "x.x.x", + "css-loader": "x.x.x", + "html-webpack-plugin": "x.x.x", + "mini-css-extract-plugin": "x.x.x", + "postcss": "x.x.x", + "postcss-loader": "x.x.x", + "react": "x.x.x", + "react-dom": "x.x.x", + "react-router-dom": "x.x.x", + "style-loader": "x.x.x", + "ts-loader": "x.x.x", + "typescript": "x.x.x", + "webpack": "x.x.x", + "webpack-cli": "x.x.x", + "webpack-dev-server": "x.x.x", + "workbox-webpack-plugin": "x.x.x", + }, + "name": "my-webpack-project", + "scripts": { + "build": "webpack --mode=production --config-node-env=production", + "build:dev": "webpack --mode=development", + "serve": "webpack serve", + "watch": "webpack --watch", + }, + "type": "module", + "version": "1.0.0", +} +`; + +exports[`create-webpack-app cli should generate react template with typescript 2`] = ` +"// Generated using webpack-cli https://github.com/webpack/webpack-cli + +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { type Configuration } from "webpack"; +import "webpack-dev-server"; +import HtmlWebpackPlugin from "html-webpack-plugin"; +import MiniCssExtractPlugin from "mini-css-extract-plugin"; +import WorkboxWebpackPlugin from "workbox-webpack-plugin"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const isProduction = process.env.NODE_ENV === "production"; +const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; + +/** @type {import("webpack").Configuration} */ +const config : Configuration = { + entry: "./src/index.tsx", + output: { + path: path.resolve(__dirname, "dist"), + }, + devServer: { + open: true, + }, + plugins: [ + new HtmlWebpackPlugin({ + template: "index.html", + }), + // Add your plugins here + // Learn more about plugins from https://webpack.js.org/configuration/plugins/ + ], + module: { + rules: [ + { + test: /\\.(ts|tsx)$/i, + loader: "ts-loader", + exclude: ["/node_modules/"], + }, + { + test: /\\.css$/i, + use: [stylesHandler, "css-loader", "postcss-loader"], + }, + { + test: /\\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i, + type: "asset", + }, + + // Add your rules for custom modules here + // Learn more about loaders from https://webpack.js.org/loaders/ + ], + }, + resolve: { + alias: { + "@": path.resolve(__dirname, "./src/"), + }, + extensions: [".jsx", ".js", ".tsx", ".ts"], + }, +}; + +export default () => { + if (isProduction) { + config.mode = "production"; + config.plugins?.push(new MiniCssExtractPlugin()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -964,12 +1048,8 @@ import WorkboxWebpackPlugin from "workbox-webpack-plugin"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - - const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; - - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/main.js", @@ -983,7 +1063,6 @@ const config = { new HtmlWebpackPlugin({ template: "./index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -1034,12 +1113,128 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - - config.plugins.push(new MiniCssExtractPlugin()); - - - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); - + config.plugins?.push(new MiniCssExtractPlugin()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); + } else { + config.mode = "development"; + } + return config; +}; +" +`; + +exports[`create-webpack-app cli should generate svelte template with typescript 1`] = ` +{ + "description": "My webpack project", + "devDependencies": { + "@tsconfig/svelte": "x.x.x", + "autoprefixer": "x.x.x", + "css-loader": "x.x.x", + "html-webpack-plugin": "x.x.x", + "mini-css-extract-plugin": "x.x.x", + "postcss": "x.x.x", + "postcss-loader": "x.x.x", + "style-loader": "x.x.x", + "svelte": "x.x.x", + "svelte-loader": "x.x.x", + "ts-loader": "x.x.x", + "typescript": "x.x.x", + "webpack": "x.x.x", + "webpack-cli": "x.x.x", + "webpack-dev-server": "x.x.x", + "workbox-webpack-plugin": "x.x.x", + }, + "name": "my-webpack-project", + "scripts": { + "build": "webpack --mode=production --config-node-env=production", + "build:dev": "webpack --mode=development", + "serve": "webpack serve", + "watch": "webpack --watch", + }, + "type": "module", + "version": "1.0.0", +} +`; + +exports[`create-webpack-app cli should generate svelte template with typescript 2`] = ` +"// Generated using webpack-cli https://github.com/webpack/webpack-cli + +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { type Configuration } from "webpack"; +import "webpack-dev-server"; +import HtmlWebpackPlugin from "html-webpack-plugin"; +import MiniCssExtractPlugin from "mini-css-extract-plugin"; +import WorkboxWebpackPlugin from "workbox-webpack-plugin"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const isProduction = process.env.NODE_ENV === "production"; +const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; + +/** @type {import("webpack").Configuration} */ +const config : Configuration = { + entry: "./src/main.ts", + output: { + path: path.resolve(__dirname, "dist"), + }, + devServer: { + open: true, + }, + plugins: [ + new HtmlWebpackPlugin({ + template: "./index.html", + }), + // Add your plugins here + // Learn more about plugins from https://webpack.js.org/configuration/plugins/ + ], + module: { + rules: [ + { + test: /\\.svelte$/, + use: { + loader: "svelte-loader", + options: { + emitCss: true, + hotReload: true + } + } + }, + { + test: /\\.ts$/, + loader: "ts-loader", + exclude: /node_modules/, + options: { + appendTsSuffixTo: [/\\.svelte$/], + }, + }, + { + test: /\\.css$/i, + use: [stylesHandler, "css-loader", "postcss-loader"], + }, + { + test: /\\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i, + type: "asset", + }, + // Add your rules for custom modules here + // Learn more about loaders from https://webpack.js.org/loaders/ + ], + }, + resolve: { + alias: { + "@": path.resolve(__dirname, "./src/"), + }, + extensions: [".mjs", ".js", ".svelte", ".ts"], + mainFields: ["svelte", "browser", "module", "main"], + conditionNames: ["svelte", "module", "browser", "main", "default"] + }, +}; + +export default () => { + if (isProduction) { + config.mode = "production"; + config.plugins?.push(new MiniCssExtractPlugin()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -1079,7 +1274,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - /** @type {import("webpack").Configuration} */ const config : Configuration = { entry: "./src/index.ts", @@ -1173,12 +1367,8 @@ import WorkboxWebpackPlugin from "workbox-webpack-plugin"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - - const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader"; - - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/main.js", @@ -1193,7 +1383,6 @@ const config = { new HtmlWebpackPlugin({ template: "index.html", }), - // Add your plugins here // Learn more about plugins from https://webpack.js.org/configuration/plugins/ ], @@ -1235,12 +1424,126 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - - config.plugins.push(new MiniCssExtractPlugin()); - - - config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); - + config.plugins?.push(new MiniCssExtractPlugin()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); + } else { + config.mode = "development"; + } + return config; +}; +" +`; + +exports[`create-webpack-app cli should generate vue template with typescript 1`] = ` +{ + "description": "My webpack project", + "devDependencies": { + "@vue/compiler-sfc": "x.x.x", + "autoprefixer": "x.x.x", + "css-loader": "x.x.x", + "html-webpack-plugin": "x.x.x", + "mini-css-extract-plugin": "x.x.x", + "pinia": "x.x.x", + "postcss": "x.x.x", + "postcss-loader": "x.x.x", + "style-loader": "x.x.x", + "ts-loader": "x.x.x", + "typescript": "x.x.x", + "vue": "x.x.x", + "vue-loader": "x.x.x", + "vue-router": "x.x.x", + "vue-style-loader": "x.x.x", + "webpack": "x.x.x", + "webpack-cli": "x.x.x", + "webpack-dev-server": "x.x.x", + "workbox-webpack-plugin": "x.x.x", + }, + "name": "my-webpack-project", + "scripts": { + "build": "webpack --mode=production --config-node-env=production", + "build:dev": "webpack --mode=development", + "serve": "webpack serve", + "watch": "webpack --watch", + }, + "type": "module", + "version": "1.0.0", +} +`; + +exports[`create-webpack-app cli should generate vue template with typescript 2`] = ` +"// Generated using webpack-cli https://github.com/webpack/webpack-cli + +import { VueLoaderPlugin } from "vue-loader"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { type Configuration } from "webpack"; +import "webpack-dev-server"; +import HtmlWebpackPlugin from "html-webpack-plugin"; +import MiniCssExtractPlugin from "mini-css-extract-plugin"; +import WorkboxWebpackPlugin from "workbox-webpack-plugin"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const isProduction = process.env.NODE_ENV === "production"; +const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader"; + +/** @type {import("webpack").Configuration} */ +const config : Configuration = { + entry: "./src/main.ts", + output: { + path: path.resolve(__dirname, "dist"), + }, + devServer: { + open: true, + }, + plugins: [ + new VueLoaderPlugin(), + new HtmlWebpackPlugin({ + template: "index.html", + }), + // Add your plugins here + // Learn more about plugins from https://webpack.js.org/configuration/plugins/ + ], + module: { + rules: [ + { + test: /\\.vue$/, + loader: "vue-loader" + }, + { + test: /\\.(ts|tsx)$/i, + loader: "ts-loader", + options: { + appendTsSuffixTo: [/\\.vue$/], + transpileOnly: true, + }, + exclude: ["/node_modules/"], + }, + { + test: /\\.css$/i, + use: [stylesHandler, "css-loader", "postcss-loader"], + }, + { + test: /\\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i, + type: "asset", + }, + // Add your rules for custom modules here + // Learn more about loaders from https://webpack.js.org/loaders/ + ], + }, + resolve: { + alias: { + "@": path.resolve(__dirname, "./src/") + }, + extensions: [".tsx", ".ts", ".js", ".vue", ".json"], + }, +}; + +export default () => { + if (isProduction) { + config.mode = "production"; + config.plugins?.push(new MiniCssExtractPlugin()); + config.plugins?.push(new WorkboxWebpackPlugin.GenerateSW()); } else { config.mode = "development"; } @@ -1285,11 +1588,8 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - - const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -1325,7 +1625,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new MiniCssExtractPlugin()); + config.plugins?.push(new MiniCssExtractPlugin()); } else { config.mode = "development"; } @@ -1370,11 +1670,8 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const isProduction = process.env.NODE_ENV === "production"; - - const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : "style-loader"; - /** @type {import("webpack").Configuration} */ const config = { entry: "./src/index.js", @@ -1406,7 +1703,7 @@ const config = { export default () => { if (isProduction) { config.mode = "production"; - config.plugins!.push(new MiniCssExtractPlugin()); + config.plugins?.push(new MiniCssExtractPlugin()); } else { config.mode = "development"; } From 63fb58b8d160f5ea3d75cf92f6921f00717801e1 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Sun, 19 Apr 2026 20:25:32 +0300 Subject: [PATCH 11/11] fix(config): preserve jsx --- .../create-webpack-app/templates/init/svelte/tsconfig.json.tpl | 1 + packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl b/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl index 8299959a98b..4570ccf6e5d 100644 --- a/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl +++ b/packages/create-webpack-app/templates/init/svelte/tsconfig.json.tpl @@ -5,6 +5,7 @@ "module": "esnext", "strict": true, "moduleResolution": "bundler", + "jsx": "preserve", "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, diff --git a/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl b/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl index 277b97be1b4..7730063adac 100644 --- a/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl +++ b/packages/create-webpack-app/templates/init/vue/tsconfig.json.tpl @@ -4,6 +4,7 @@ "module": "esnext", "strict": true, "jsx": "preserve", + "jsxImportSource": "vue", "moduleResolution": "bundler", "skipLibCheck": true, "esModuleInterop": true,