webpack.conf.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. const { modifyWebpackConfig, shallowMerge, defaultOptions } = require('@gera2ld/plaid');
  2. const { isProd } = require('@gera2ld/plaid/util');
  3. const webpack = require('webpack');
  4. const WrapperWebpackPlugin = require('wrapper-webpack-plugin');
  5. const TerserPlugin = require('terser-webpack-plugin');
  6. const projectConfig = require('./plaid.conf');
  7. const mergedConfig = shallowMerge(defaultOptions, projectConfig);
  8. const INIT_FUNC_NAME = 'VMInitInjection';
  9. // Copied from gulpfile.js: strip alphabetic suffix
  10. const VM_VER = require('../package.json').version.replace(/-[^.]*/, '');
  11. const definitions = new webpack.DefinePlugin({
  12. 'process.env.INIT_FUNC_NAME': JSON.stringify(INIT_FUNC_NAME),
  13. 'process.env.DEBUG': JSON.stringify(process.env.DEBUG || false),
  14. 'process.env.VM_VER': JSON.stringify(VM_VER),
  15. });
  16. const minimizerOptions = {
  17. cache: true,
  18. parallel: true,
  19. sourceMap: true,
  20. terserOptions: {
  21. output: {
  22. ascii_only: true,
  23. },
  24. },
  25. };
  26. const minimizer = isProd && [
  27. new TerserPlugin({
  28. chunkFilter: ({ name }) => !name.startsWith('public/'),
  29. ...minimizerOptions,
  30. terserOptions: {
  31. ...minimizerOptions.terserOptions,
  32. compress: {
  33. ecma: 6,
  34. // 'safe' since we don't rely on function prototypes
  35. unsafe_arrows: true,
  36. },
  37. },
  38. }),
  39. new TerserPlugin({
  40. chunkFilter: ({ name }) => name.startsWith('public/'),
  41. ...minimizerOptions,
  42. }),
  43. ];
  44. const modify = (extra, init) => modifyWebpackConfig(
  45. (config) => {
  46. config.plugins.push(definitions);
  47. if (init) init(config);
  48. return config;
  49. }, {
  50. projectConfig: {
  51. ...mergedConfig,
  52. ...extra,
  53. optimization: {
  54. ...mergedConfig.optimization,
  55. ...(extra || {}).pages && {
  56. runtimeChunk: false,
  57. splitChunks: false,
  58. },
  59. minimizer,
  60. },
  61. },
  62. },
  63. );
  64. // avoid running webpack bootstrap in a potentially hacked environment
  65. // after documentElement was replaced which triggered reinjection of content scripts
  66. const skipReinjectionHeader = `if (window['${INIT_FUNC_NAME}'] !== 1)`;
  67. const skipReinjectionConfig = (config, test) => config.plugins.push(
  68. new WrapperWebpackPlugin({
  69. header: skipReinjectionHeader,
  70. ...test && { test },
  71. }));
  72. module.exports = Promise.all([
  73. modify(null, config => skipReinjectionConfig(config, /^browser\.js$/)),
  74. modify({
  75. pages: {
  76. injected: {
  77. entry: './src/injected',
  78. },
  79. },
  80. }, skipReinjectionConfig),
  81. modify({
  82. pages: {
  83. 'injected-web': {
  84. entry: './src/injected/web',
  85. },
  86. },
  87. }, (config) => {
  88. config.output.libraryTarget = 'commonjs2';
  89. config.plugins.push(
  90. new WrapperWebpackPlugin({
  91. header: `${skipReinjectionHeader}
  92. window['${INIT_FUNC_NAME}'] = function () {
  93. var module = { exports: {} };
  94. `,
  95. footer: `
  96. var exports = module.exports;
  97. return exports.__esModule ? exports['default'] : exports;
  98. };0;`,
  99. }),
  100. );
  101. }),
  102. ]);