CorsPlugin.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. const HtmlWebpackPlugin = require('html-webpack-plugin')
  2. module.exports = class CorsPlugin {
  3. constructor ({ publicPath, crossorigin, integrity }) {
  4. this.crossorigin = crossorigin
  5. this.integrity = integrity
  6. this.publicPath = publicPath
  7. }
  8. apply (compiler) {
  9. const ID = `vue-cli-cors-plugin`
  10. compiler.hooks.compilation.tap(ID, compilation => {
  11. const ssri = require('ssri')
  12. const computeHash = url => {
  13. const filename = url.replace(this.publicPath, '')
  14. const asset = compilation.assets[filename]
  15. if (asset) {
  16. const src = asset.source()
  17. const integrity = ssri.fromData(src, {
  18. algorithms: ['sha384']
  19. })
  20. return integrity.toString()
  21. }
  22. }
  23. HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tap(ID, data => {
  24. const tags = [...data.headTags, ...data.bodyTags]
  25. if (this.crossorigin != null) {
  26. tags.forEach(tag => {
  27. if (tag.tagName === 'script' || tag.tagName === 'link') {
  28. tag.attributes.crossorigin = this.crossorigin
  29. }
  30. })
  31. }
  32. if (this.integrity) {
  33. tags.forEach(tag => {
  34. if (tag.tagName === 'script') {
  35. const hash = computeHash(tag.attributes.src)
  36. if (hash) {
  37. tag.attributes.integrity = hash
  38. }
  39. } else if (tag.tagName === 'link' && tag.attributes.rel === 'stylesheet') {
  40. const hash = computeHash(tag.attributes.href)
  41. if (hash) {
  42. tag.attributes.integrity = hash
  43. }
  44. }
  45. })
  46. // when using SRI, Chrome somehow cannot reuse
  47. // the preloaded resource, and causes the files to be downloaded twice.
  48. // this is a Chrome bug (https://bugs.chromium.org/p/chromium/issues/detail?id=677022)
  49. // for now we disable preload if SRI is used.
  50. data.headTags = data.headTags.filter(tag => {
  51. return !(
  52. tag.tagName === 'link' &&
  53. tag.attributes.rel === 'preload'
  54. )
  55. })
  56. }
  57. })
  58. HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tap(ID, data => {
  59. data.html = data.html.replace(/\scrossorigin=""/g, ' crossorigin')
  60. })
  61. })
  62. }
  63. }