I have a vue application that is piled using vue-cli. My vue.config.js file looks like:
'use strict';
module.exports = {
publicPath: `${process.env.CDN_URL || ''}/dist/`,
lintOnSave: true,
transpileDependencies: [],
outputDir: '.tmp/dist',
pages: {
navigator: {
entry: 'vue/home/main.ts',
template: 'views/home/index.ejs',
// Will output to dist/views/home/index.ejs
filename: 'views/home/index.ejs',
},
},
chainWebpack(config) {
// Override the default loader for html-webpack-plugin so that it does not fallback to ejs-loader.
// ejs-loader will use ejs syntax against the template file to inject dynamic values before html-webpack-plugin runs
config.module
.rule('ejs')
.test(/\.ejs$/)
.use('html')
.loader('html-loader');
},
};
I would like to have webpack add nonce="<%= nonce %>"
for each script tag that it generates. I see that webpack has a __webpack_nonce__
variable, but I've tried setting that in many parts of the vue.config.js file. I've tried adding it to chainWebpack() and configWebpack(). I've tried adding it to the vue/home/main.ts file. Nothing seems to work. How do I get nonce attributes added to the script tags?
This is vue 2.6.x and vue cli 4.5.x
I have a vue application that is piled using vue-cli. My vue.config.js file looks like:
'use strict';
module.exports = {
publicPath: `${process.env.CDN_URL || ''}/dist/`,
lintOnSave: true,
transpileDependencies: [],
outputDir: '.tmp/dist',
pages: {
navigator: {
entry: 'vue/home/main.ts',
template: 'views/home/index.ejs',
// Will output to dist/views/home/index.ejs
filename: 'views/home/index.ejs',
},
},
chainWebpack(config) {
// Override the default loader for html-webpack-plugin so that it does not fallback to ejs-loader.
// ejs-loader will use ejs syntax against the template file to inject dynamic values before html-webpack-plugin runs
config.module
.rule('ejs')
.test(/\.ejs$/)
.use('html')
.loader('html-loader');
},
};
I would like to have webpack add nonce="<%= nonce %>"
for each script tag that it generates. I see that webpack has a __webpack_nonce__
variable, but I've tried setting that in many parts of the vue.config.js file. I've tried adding it to chainWebpack() and configWebpack(). I've tried adding it to the vue/home/main.ts file. Nothing seems to work. How do I get nonce attributes added to the script tags?
This is vue 2.6.x and vue cli 4.5.x
Share Improve this question asked Sep 22, 2020 at 22:08 Jim GeurtsJim Geurts 20.4k24 gold badges99 silver badges117 bronze badges3 Answers
Reset to default 7I ended up writing my own webpack plugin since my use case was a bit more plex than what script-ext-html-webpack-plugin could support. I needed ${nonce}
for header tags and <%= nonce %>
for body tags. My plugin code is a simple and based off script-ext-html-webpack-plugin mentioned by @Sphinx
const HtmlWebpackPlugin = require('html-webpack-plugin');
class AddNonceToScriptTagsWebpackPlugin {
apply(piler) {
piler.hooks.pilation.tap(this.constructor.name, (pilation) => {
const alterAssetTagGroups = pilation.hooks.htmlWebpackPluginAlterAssetTags || HtmlWebpackPlugin.getHooks(pilation).alterAssetTagGroups;
alterAssetTagGroups.tap(this.constructor.name, (data) => {
data.head = this._addNonceAttribute(data.head || []);
data.body = this._addNonceAttribute(data.body || []);
return data;
});
});
}
_addNonceAttribute(tags) {
return tags.map((tag) => {
if (tag.tagName === 'script') {
tag.attributes = tag.attributes || {};
tag.attributes.nonce = '<%= nonce %>';
} else if (tag.tagName === 'link' && tag.attributes && tag.attributes.as === 'script') {
tag.attributes = tag.attributes || {};
// eslint-disable-next-line no-template-curly-in-string
tag.attributes.nonce = '${nonce}';
}
return tag;
});
}
}
The updated vue.config.js file then looks like:
'use strict';
module.exports = {
publicPath: `${process.env.CDN_URL || ''}/dist/`,
lintOnSave: true,
transpileDependencies: [],
outputDir: '.tmp/dist',
pages: {
navigator: {
entry: 'vue/home/main.ts',
template: 'views/home/index.ejs',
// Will output to dist/views/home/index.ejs
filename: 'views/home/index.ejs',
},
},
configureWebpack: {
plugins: [
new AddNonceToScriptTagsWebpackPlugin(),
],
},
chainWebpack(config) {
// Override the default loader for html-webpack-plugin so that it does not fallback to ejs-loader.
// ejs-loader will use ejs syntax against the template file to inject dynamic values before html-webpack-plugin runs
config.module
.rule('ejs')
.test(/\.ejs$/)
.use('html')
.loader('html-loader');
},
};
One solution should be adds script-ext-html-webpack-plugin into the plugin list of webpack.prod.conf
file (or your own webpack configuration file).
new ScriptExtHtmlWebpackPlugin({
custom: {
test: /\.js$/, // adjust this regex based on your demand
attribute: 'nonce',
value: '<%= nonce %>'
}
}),
3 years, yet I'm still finding the best answer here
I made some changes & clarifications based on @Jim Geurts solution
on vue.config.js add
class AddNonceToScriptTagsWebpackPlugin {
apply(piler) {
piler.hooks.pilation.tap(this.constructor.name, (pilation) => {
const alterAssetTagGroups = pilation.hooks.htmlWebpackPluginAlterAssetTags || HtmlWebpackPlugin.getHooks(pilation).alterAssetTagGroups;
alterAssetTagGroups.tap(this.constructor.name, (data) => {
data.head = this._addNonceAttribute(data.head || []);
data.body = this._addNonceAttribute(data.body || []);
return data;
});
});
}
_addNonceAttribute(tags) {
return tags.map((tag) => {
if (tag.tagName === 'script' || tag.tagName === 'link' || tag.tagName === 'style') {
tag.attributes = tag.attributes || {};
tag.attributes.nonce = 'YOUR-SECRET-NONCE';
}
return tag;
});
}
}
but Jim Code or mine will minimize the HTML output (index.html) to inline (removing space / enter). and the solution is by custom the HtmlWebpackPlugin config
configureWebpack: {
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: 'body', // Inject scripts into body
minify: false, // Disable minification
}),
new AddNonceToScriptTagsWebpackPlugin(),
]
}