diff --git a/CHANGELOG.md b/CHANGELOG.md index 97134db83..f9246ad8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,43 @@ # CHANGELOG -## v4.6.0 +## UNRELEASED -* #1254 Increased minimum Node version to 20 (@weaverryan) +* #1295 Add JSX support for Vue 3 (@Kocal) -* #1253 Allow sass-loader 14 (@cedric-anne) +Enabling JSX support for Vue 3 is done with the `Encore.enableVueLoader()`: +```js +Encore.enableVueLoader(() => {}, { + useJsx: true, + version: 3, +}); +``` -* #1247 Allow only configuring a plugin (@gimler) +If you don't have a custom Babel configuration, then you're all set! +But if you do, you may need to adjust it +to add [`@vue/babel-plugin-jsx`](https://github.com/vuejs/babel-plugin-jsx) plugin to your Babel configuration: +```js +// babel.config.js +module.exports = { + plugins: [ + '@vue/babel-plugin-jsx' + ] +}; +``` -## v4.5.0 -* #1235 Dropping support for Node 14 (16 is new min) and allowing `svelte` 4 (@weaverryan) +## [v4.6.1](https://github.com/symfony/webpack-encore/releases/tag/v4.6.1) -* #1185 Bump `babel-loader` from 8.2.5 to 9.1.2 (@dppanteon) - the - [CHANGELOG for babel 9](https://github.com/babel/babel-loader/releases/tag/v9.0.0) - does not list any breaking changes besides increasing the minimum Node version. +* #1256 Re-adding node 18 support (@weaverryan) -* #1224 Allow fork-ts-checker-webpack-plugin ^8.0 and ^9.0 (@buffcode) +## [v4.6.0](https://github.com/symfony/webpack-encore/releases/tag/v4.6.0) + +* #1254 Increased minimum Node version to 20 (@weaverryan) + +* #1253 Allow sass-loader 14 (@cedric-anne) + +* #1247 Allow only configuring a plugin (@gimler) -## [v4.4.0](https://github.com/symfony/webpack-encore/releases/tag/v4.5.0) +## [v4.5.0](https://github.com/symfony/webpack-encore/releases/tag/v4.5.0) ### Features diff --git a/fixtures/vuejs-jsx/main_v3.js b/fixtures/vuejs-jsx/main_v3.js new file mode 100644 index 000000000..f903f0159 --- /dev/null +++ b/fixtures/vuejs-jsx/main_v3.js @@ -0,0 +1,6 @@ +import { createApp } from 'vue' +import App from './App' + +const app = createApp(App); + +app.mount('#app'); diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 3744913f1..1232d4c30 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -763,11 +763,6 @@ class WebpackConfig { this.vueOptions[key] = vueOptions[key]; } - - // useJsx and vue 3 are not currently supported by Encore - if (this.vueOptions.useJsx && this.vueOptions.version === 3) { - throw new Error('Setting both "useJsx: true" and "version: 3" for enableVueLoader() is not currently supported. Please use version: 2 or disable useJsx.'); - } } enableEslintPlugin(eslintPluginOptionsOrCallback = () => {}) { diff --git a/lib/features.js b/lib/features.js index e85692a4b..9be8a530c 100644 --- a/lib/features.js +++ b/lib/features.js @@ -124,6 +124,13 @@ const features = { ], description: 'use Vue with JSX support' }, + 'vue3-jsx': { + method: 'enableVueLoader()', + packages: [ + { name: '@vue/babel-plugin-jsx' }, + ], + description: 'use Vue with JSX support' + }, eslint_plugin: { method: 'enableEslintPlugin()', // eslint is needed so the end-user can do things diff --git a/lib/loaders/babel.js b/lib/loaders/babel.js index bd5a9b6d3..3efa815a2 100644 --- a/lib/loaders/babel.js +++ b/lib/loaders/babel.js @@ -88,8 +88,14 @@ module.exports = { } if (webpackConfig.useVueLoader && webpackConfig.vueOptions.useJsx) { - loaderFeatures.ensurePackagesExistAndAreCorrectVersion('vue-jsx'); - babelConfig.presets.push(require.resolve('@vue/babel-preset-jsx')); + // TODO v5: Only keep the v3 code path + if (webpackConfig.vueOptions.version === 3) { + loaderFeatures.ensurePackagesExistAndAreCorrectVersion('vue3-jsx'); + babelConfig.plugins.push(require.resolve('@vue/babel-plugin-jsx')); + } else { + loaderFeatures.ensurePackagesExistAndAreCorrectVersion('vue-jsx'); + babelConfig.presets.push(require.resolve('@vue/babel-preset-jsx')); + } } babelConfig = applyOptionsCallback(webpackConfig.babelConfigurationCallback, babelConfig); diff --git a/package.json b/package.json index 8908f026a..7ab6f5712 100755 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "@symfony/mock-module": "file:fixtures/stimulus/mock-module", "@symfony/stimulus-bridge": "^3.0.0", "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "@vue/babel-plugin-jsx": "^1.0.0", "@vue/babel-preset-jsx": "^1.0.0", "@vue/compiler-sfc": "^3.0.2", "autoprefixer": "^10.2.0", @@ -110,6 +111,7 @@ "@babel/preset-typescript": "^7.0.0", "@symfony/stimulus-bridge": "^3.0.0", "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "@vue/babel-plugin-jsx": "^1.0.0", "@vue/babel-preset-jsx": "^1.0.0", "@vue/compiler-sfc": "^2.6 || ^3.0.2", "eslint": "^8.0.0", @@ -157,6 +159,9 @@ "@vue/babel-helper-vue-jsx-merge-props": { "optional": true }, + "@vue/babel-plugin-jsx": { + "optional": true + }, "@vue/babel-preset-jsx": { "optional": true }, diff --git a/test/functional.js b/test/functional.js index 9d58b0252..b81ef1239 100644 --- a/test/functional.js +++ b/test/functional.js @@ -1707,25 +1707,20 @@ module.exports = { const config = testSetup.createWebpackConfig(appDir, 'www/build', 'dev'); - if (getVueVersion(config) === 3) { - // not supported for vue3 at this time - this.skip(); - - return; - } - config.enableSingleRuntimeChunk(); config.setPublicPath('/build'); config.addEntry('main', `./vuejs-jsx/main_v${getVueVersion(config)}`); config.enableVueLoader(() => {}, { useJsx: true, + version: getVueVersion(config), }); config.enableSassLoader(); config.enableLessLoader(); config.configureBabel(function(config) { - expect(config.presets[0][0]).to.equal('@babel/preset-env'); + // throw new Error(JSON.stringify(config)); + expect(config.presets[0][0]).to.equal(require.resolve('@babel/preset-env')); config.presets[0][1].targets = { - chrome: 52 + chrome: 109 }; }); diff --git a/yarn.lock b/yarn.lock index 1f0d81ea6..04ff9342b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -160,7 +160,7 @@ dependencies: "@babel/types" "^7.23.0" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.22.15": +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@~7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== @@ -1542,6 +1542,39 @@ resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz#8d53a1e21347db8edbe54d339902583176de09f2" integrity sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA== +"@vue/babel-helper-vue-transform-on@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.2.2.tgz#7f1f817a4f00ad531651a8d1d22e22d9e42807ef" + integrity sha512-nOttamHUR3YzdEqdM/XXDyCSdxMA9VizUKoroLX6yTyRtggzQMHXcmwh8a7ZErcJttIBIc9s68a1B8GZ+Dmvsw== + +"@vue/babel-plugin-jsx@^1.0.0": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.2.2.tgz#eb426fb4660aa510bb8d188ff0ec140405a97d8a" + integrity sha512-nYTkZUVTu4nhP199UoORePsql0l+wj7v/oyQjtThUVhJl1U+6qHuoVhIvR3bf7eVKjbCK+Cs2AWd7mi9Mpz9rA== + dependencies: + "@babel/helper-module-imports" "~7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.23.3" + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + "@vue/babel-helper-vue-transform-on" "1.2.2" + "@vue/babel-plugin-resolve-type" "1.2.2" + camelcase "^6.3.0" + html-tags "^3.3.1" + svg-tags "^1.0.0" + +"@vue/babel-plugin-resolve-type@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.2.2.tgz#66844898561da6449e0f4a261b0c875118e0707b" + integrity sha512-EntyroPwNg5IPVdUJupqs0CFzuf6lUrVvCspmv2J1FITLeGnUCuoGNNk78dgCusxEiYj6RMkTJflGSxk5aIC4A== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/helper-module-imports" "~7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/parser" "^7.23.9" + "@vue/compiler-sfc" "^3.4.15" + "@vue/babel-plugin-transform-vue-jsx@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.4.0.tgz#4d4b3d46a39ea62b7467dd6e26ce47f7ceafb2fe" @@ -1655,7 +1688,7 @@ "@vue/compiler-core" "3.4.38" "@vue/shared" "3.4.38" -"@vue/compiler-sfc@3.4.38": +"@vue/compiler-sfc@3.4.38", "@vue/compiler-sfc@^3.4.15": version "3.4.38" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz#954c3f6777bbbcca28771ba59b795f12f76ef188" integrity sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ== @@ -2417,7 +2450,7 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -4170,6 +4203,11 @@ html-tags@^2.0.0: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" integrity sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g== +html-tags@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" + integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== + htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"