webpack.conf.js 3.0 KB

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