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();