diff --git a/CHANGELOG.md b/CHANGELOG.md index e5efe408..59117efb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,27 +2,8 @@ ## 0.30.0 - * [BC BREAK] The Vue "build" was changed from `vue.esm.js` (full build) to - `vue.runtime.esm.js` (runtime build). With the runtime build, there are - two things that you cannot do: - - A) You cannot pass a string to `template`: - - ```js - new Vue({ - template: '
{{ hi }}
' - }) - ``` - - B) You cannot mount to a DOM element and use its HTML as your template: - - ```js - new Vue({ - el: '#app', // where
contains your Vue template - }); - ``` - - If you need this behavior, call `Encore.addAliases({ vue$: 'vue/dist/vue.esm.js' });` + * ~~[BC BREAK] The Vue "build" was changed from `vue.esm.js` (full build) to `vue.runtime.esm.js` (runtime build)~~ + This was reverted in Encore 0.30.1. * [DEPENDENCY UPGRADE] `sass-loader` was upgraded from version 7 to 8. See the [CHANGELOG](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md#800-2019-08-29) diff --git a/index.js b/index.js index e0f5fcfe..af778c63 100644 --- a/index.js +++ b/index.js @@ -1150,6 +1150,12 @@ class Encore { * Encore.enableVueLoader(() => {}, { * // set optional Encore-specific options, for instance: * + * // set to false to *only* include the smaller "runtime" + * // build, which can't compile templates at runtime, but is + * // CSP compliant/ + * // set explicitly to true to silence the recommendation + * runtimeCompilerBuild: false + * * // use version 2 or 3 to force your Vue version * // otherwise, Encore will detect it automatically * version: 2 diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index c9de5fcd..770471b2 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -137,6 +137,7 @@ class WebpackConfig { this.vueOptions = { useJsx: false, version: null, + runtimeCompilerBuild: null }; this.eslintOptions = { lintVue: false, diff --git a/lib/config-generator.js b/lib/config-generator.js index e71e92b4..e96bd4ba 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -43,6 +43,7 @@ const PluginPriorities = require('./plugins/plugin-priorities'); const applyOptionsCallback = require('./utils/apply-options-callback'); const sharedEntryTmpName = require('./utils/sharedEntryTmpName'); const copyEntryTmpName = require('./utils/copyEntryTmpName'); +const getVueVersion = require('./utils/get-vue-version'); const tmp = require('tmp'); const fs = require('fs'); const path = require('path'); @@ -100,6 +101,24 @@ class ConfigGenerator { alias: {} }; + if (this.webpackConfig.useVueLoader && (this.webpackConfig.vueOptions.runtimeCompilerBuild === true || this.webpackConfig.vueOptions.runtimeCompilerBuild === null)) { + if (this.webpackConfig.vueOptions.runtimeCompilerBuild === null) { + logger.recommendation('To create a smaller (and CSP-compliant) build, see https://symfony.com/doc/current/frontend/encore/vuejs.html#runtime-compiler-build'); + } + + const vueVersion = getVueVersion(this.webpackConfig); + switch (vueVersion) { + case 2: + config.resolve.alias['vue$'] = 'vue/dist/vue.esm.js'; + break; + case 3: + config.resolve.alias['vue$'] = 'vue/dist/vue.esm-bundler.js'; + break; + default: + throw new Error(`Invalid vue version ${vueVersion}`); + } + } + if (this.webpackConfig.usePreact && this.webpackConfig.preactOptions.preactCompat) { config.resolve.alias['react'] = 'preact-compat'; config.resolve.alias['react-dom'] = 'preact-compat'; diff --git a/lib/friendly-errors/transformers/missing-loader.js b/lib/friendly-errors/transformers/missing-loader.js index f3256968..1bec1a72 100644 --- a/lib/friendly-errors/transformers/missing-loader.js +++ b/lib/friendly-errors/transformers/missing-loader.js @@ -32,7 +32,11 @@ function isErrorFromVueLoader(filename) { } // vue3 - if (filename.includes('vue-loader/dist??')) { + if (/vue-loader\/dist(\/index\.js)?\?\?/.test(filename)) { + return true; + } + // later vue3 variant + if (filename.includes('?vue') && filename.includes('lang=')) { return true; } diff --git a/lib/utils/manifest-key-prefix-helper.js b/lib/utils/manifest-key-prefix-helper.js index 44b83082..e7b2b027 100644 --- a/lib/utils/manifest-key-prefix-helper.js +++ b/lib/utils/manifest-key-prefix-helper.js @@ -20,6 +20,10 @@ const WebpackConfig = require('../WebpackConfig'); //eslint-disable-line no-unus module.exports = function(webpackConfig) { let manifestPrefix = webpackConfig.manifestKeyPrefix; if (null === manifestPrefix) { + if (null === webpackConfig.publicPath) { + throw new Error('publicPath is not set on WebpackConfig'); + } + // by convention, we remove the opening slash on the manifest keys manifestPrefix = webpackConfig.publicPath.replace(/^\//, ''); } diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index 094cb6e7..3b2a2f52 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -1039,7 +1039,7 @@ describe('WebpackConfig object', () => { config.enableVueLoader(() => {}, { notExisting: false, }); - }).to.throw('"notExisting" is not a valid key for enableVueLoader(). Valid keys: useJsx, version.'); + }).to.throw('"notExisting" is not a valid key for enableVueLoader(). Valid keys: useJsx, version, runtimeCompilerBuild.'); }); it('Should set Encore-specific options', () => { @@ -1049,6 +1049,7 @@ describe('WebpackConfig object', () => { }); expect(config.vueOptions).to.deep.equal({ + runtimeCompilerBuild: null, useJsx: true, version: null, }); diff --git a/test/config-generator.js b/test/config-generator.js index 3a0d8e7d..61910803 100644 --- a/test/config-generator.js +++ b/test/config-generator.js @@ -447,6 +447,34 @@ describe('The config-generator function', () => { }); }); + describe('enableVueLoader() with runtimeCompilerBuild sets Vue alias', () => { + it('defaults to "true"', () => { + const config = createConfig(); + config.outputPath = '/tmp/output/public-path'; + config.publicPath = '/public-path'; + config.enableSingleRuntimeChunk(); + config.enableVueLoader(() => {}, { version: 3 }); + + const actualConfig = configGenerator(config); + + expect(actualConfig.resolve.alias).to.deep.equals({ + 'vue$': 'vue/dist/vue.esm-bundler.js', + }); + }); + + it('no alias for false', () => { + const config = createConfig(); + config.outputPath = '/tmp/output/public-path'; + config.publicPath = '/public-path'; + config.enableSingleRuntimeChunk(); + config.enableVueLoader(() => {}, { version: 3, runtimeCompilerBuild: false }); + + const actualConfig = configGenerator(config); + + expect(actualConfig.resolve.alias).to.deep.empty; + }); + }); + describe('addAliases() adds new aliases', () => { it('without addAliases()', () => { const config = createConfig();