webpack.conf.js 2.8 KB

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