webpack.conf.js 3.6 KB

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