最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to configure a vue application (with vue-cli) to add nonce attributes to generated script tags? - Stack Overflo

programmeradmin0浏览0评论

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 badges
Add a ment  | 

3 Answers 3

Reset to default 7

I 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(),
    ]
  }

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论