Vue-cli: Option to build with --modern and remove inline Safari script

Created on 21 Sep 2018  路  2Comments  路  Source: vuejs/vue-cli

Version

3.0.3

Node and OS info

N/A

Steps to reproduce

From the docs:

Also, modern mode uses an inline script to avoid Safari 10 loading both bundles, so if you are using a strict CSP, you will need to explicitly allow the inline script

What is expected?

There would be a flag or config variable to not force modification of CSP, by removing the Safari workaround

What is actually happening?

If we use --modern, we are forced to modify the CSP. This is not always practical for large organisations with slower bureaucratic processes.

contribution welcome enhancement intend to implement cli-service build

Most helpful comment

If anyone is totally blocked on this attached is a quick and dirty plugin to inline the safari fix and remove it from the html.

to use it just add

vue.config.js

const SafariExternalizerPlugin = require('./SafariExternalizerPlugin.js');
module.exports = {
 chainWebpack: (config) => {
    if (process.env.VUE_CLI_BUILD_TARGET === 'app') {
      config.plugin('safari-externalizer-plugin')
          .use(SafariExternalizerPlugin);
    }
 }
}

SafariExternalizerPlugin.js

const safariFix = require('@vue/cli-service/lib/webpack/ModernModePlugin.js').safariFix;

class SafariExternalizerPlugin {
  constructor ({filename = '_safari-legacy.js'} = {}) {
    this.filename = filename;
  }

  apply (compiler) {
    const isModern = process.env.VUE_CLI_MODERN_BUILD;
    if (!isModern) {
      this.applyLegacy(compiler)
    }

    this.applyAddSafariAsset(compiler);
    this.applyStripInlineStyle(compiler);
  }

  applyLegacy (compiler) {
    const ID = `modern-externalizer-legacy-script`;
    compiler.hooks.compilation.tap(ID, compilation => {
      compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(ID, async (data, cb) => {
        data.body.unshift({
          tagName: 'script',
          closeTag: true,
          attributes: {
            type: 'text/javascript',
            src: `${process.env.NODE_ENV === 'production' ? 'js/' : ''}${this.filename}`
          }
        });
        cb();
      })
    })
  }

  applyAddSafariAsset (compiler) {
    const ID = `modern-externalizer-safari-asset`;
    compiler.hooks.compilation.tap(ID, compilation => {
      compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(ID, async (data, cb) => {
        compilation.assets
            [`${process.env.NODE_ENV === 'production' ? 'js/' : ''}${this.filename}`] =
            {
              source: function () {
                return new Buffer(safariFix);
              },
              size: function () {
                return Buffer.byteLength(safariFix);
              }
            };
        cb();
      });
    });
  }

  applyStripInlineStyle (compiler) {
    const ID = `modern-externalizer-strip-inline`;
    compiler.hooks.compilation.tap(ID, compilation => {
      compilation.hooks.htmlWebpackPluginAfterHtmlProcessing.tapAsync(ID, async (data, cb) => {
        if (data && data.html) {
          data.html = data.html.replace(`<script>${safariFix}</script>`, '');
        }
        cb();
      });
    });
  }
}

module.exports = SafariExternalizerPlugin;

All 2 comments

馃憤 for this please.

I know it was mentioned here (https://github.com/vuejs/vue-cli/issues/2001) but there are a lot of cases where we do not have control over the policy and taking the extra request is better then losing modern builds.

If anyone is totally blocked on this attached is a quick and dirty plugin to inline the safari fix and remove it from the html.

to use it just add

vue.config.js

const SafariExternalizerPlugin = require('./SafariExternalizerPlugin.js');
module.exports = {
 chainWebpack: (config) => {
    if (process.env.VUE_CLI_BUILD_TARGET === 'app') {
      config.plugin('safari-externalizer-plugin')
          .use(SafariExternalizerPlugin);
    }
 }
}

SafariExternalizerPlugin.js

const safariFix = require('@vue/cli-service/lib/webpack/ModernModePlugin.js').safariFix;

class SafariExternalizerPlugin {
  constructor ({filename = '_safari-legacy.js'} = {}) {
    this.filename = filename;
  }

  apply (compiler) {
    const isModern = process.env.VUE_CLI_MODERN_BUILD;
    if (!isModern) {
      this.applyLegacy(compiler)
    }

    this.applyAddSafariAsset(compiler);
    this.applyStripInlineStyle(compiler);
  }

  applyLegacy (compiler) {
    const ID = `modern-externalizer-legacy-script`;
    compiler.hooks.compilation.tap(ID, compilation => {
      compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(ID, async (data, cb) => {
        data.body.unshift({
          tagName: 'script',
          closeTag: true,
          attributes: {
            type: 'text/javascript',
            src: `${process.env.NODE_ENV === 'production' ? 'js/' : ''}${this.filename}`
          }
        });
        cb();
      })
    })
  }

  applyAddSafariAsset (compiler) {
    const ID = `modern-externalizer-safari-asset`;
    compiler.hooks.compilation.tap(ID, compilation => {
      compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(ID, async (data, cb) => {
        compilation.assets
            [`${process.env.NODE_ENV === 'production' ? 'js/' : ''}${this.filename}`] =
            {
              source: function () {
                return new Buffer(safariFix);
              },
              size: function () {
                return Buffer.byteLength(safariFix);
              }
            };
        cb();
      });
    });
  }

  applyStripInlineStyle (compiler) {
    const ID = `modern-externalizer-strip-inline`;
    compiler.hooks.compilation.tap(ID, compilation => {
      compilation.hooks.htmlWebpackPluginAfterHtmlProcessing.tapAsync(ID, async (data, cb) => {
        if (data && data.html) {
          data.html = data.html.replace(`<script>${safariFix}</script>`, '');
        }
        cb();
      });
    });
  }
}

module.exports = SafariExternalizerPlugin;
Was this page helpful?
0 / 5 - 0 ratings

Related issues

wahidrahim picture wahidrahim  路  3Comments

b-zee picture b-zee  路  3Comments

OmgImAlexis picture OmgImAlexis  路  3Comments

joshuajohnson814 picture joshuajohnson814  路  3Comments

BusyHe picture BusyHe  路  3Comments