webpack.conf.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. const { resolve } = require('path');
  2. const webpack = require('webpack');
  3. const { ListBackgroundScriptsPlugin } = require('./manifest-helper');
  4. const { addWrapperWithGlobals, getCodeMirrorThemes } = require('./webpack-util');
  5. const ProtectWebpackBootstrapPlugin = require('./webpack-protect-bootstrap-plugin');
  6. const { getVersion } = require('./version-helper');
  7. const { configLoader } = require('./config-helper');
  8. const { getBaseConfig, getPageConfig, isProd } = require('./webpack-base');
  9. // Avoiding collisions with globals of a content-mode userscript
  10. const INIT_FUNC_NAME = '**VMInitInjection**';
  11. const VAULT_ID = 'VAULT_ID';
  12. const PAGE_MODE_HANDSHAKE = 'PAGE_MODE_HANDSHAKE';
  13. const VM_VER = getVersion();
  14. global.localStorage = {}; // workaround for node 25 and HtmlWebpackPlugin's `...global`
  15. configLoader
  16. // Default values
  17. .add({
  18. DEBUG: false,
  19. })
  20. // Load from `./.env`
  21. .envFile()
  22. // Load from `process.env`
  23. .env()
  24. // Override values
  25. .add({
  26. VM_VER,
  27. });
  28. const pickEnvs = (items) => {
  29. return Object.assign({}, ...items.map(key => ({
  30. [`process.env.${key}`]: JSON.stringify(configLoader.get(key)),
  31. })));
  32. };
  33. const defsObj = {
  34. ...pickEnvs([
  35. 'DEBUG',
  36. 'VM_VER',
  37. 'SYNC_GOOGLE_DESKTOP_ID',
  38. 'SYNC_GOOGLE_DESKTOP_SECRET',
  39. 'SYNC_ONEDRIVE_CLIENT_ID',
  40. 'SYNC_DROPBOX_CLIENT_ID',
  41. ]),
  42. 'process.env.INIT_FUNC_NAME': JSON.stringify(INIT_FUNC_NAME),
  43. 'process.env.CODEMIRROR_THEMES': JSON.stringify(getCodeMirrorThemes()),
  44. 'process.env.DEV': JSON.stringify(!isProd),
  45. 'process.env.TEST': JSON.stringify(process.env.BABEL_ENV === 'test'),
  46. };
  47. // avoid running webpack bootstrap in a potentially hacked environment
  48. // after documentElement was replaced which triggered reinjection of content scripts
  49. const skipReinjectionHeader = `{
  50. const INIT_FUNC_NAME = '${INIT_FUNC_NAME}';
  51. if (window[INIT_FUNC_NAME] !== 1)`;
  52. const buildConfig = (page, entry, init) => {
  53. const config = entry ? getBaseConfig() : getPageConfig();
  54. config.plugins.push(new webpack.DefinePlugin({
  55. ...defsObj,
  56. // Conditional compilation to remove unsafe and unused stuff from `injected`
  57. 'process.env.IS_INJECTED': JSON.stringify(/injected/.test(page) && page),
  58. }));
  59. if (typeof entry === 'string') {
  60. config.entry = { [page]: entry };
  61. }
  62. if (!entry) init = page;
  63. if (init) init(config);
  64. return config;
  65. };
  66. module.exports = [
  67. buildConfig((config) => {
  68. addWrapperWithGlobals('common', config, defsObj, getGlobals => ({
  69. header: () => `{ ${getGlobals()}`,
  70. footer: '}',
  71. test: /^(?!injected|public).*\.js$/,
  72. }));
  73. config.plugins.push(new ListBackgroundScriptsPlugin({
  74. minify: false, // keeping readable
  75. }));
  76. config.resolve.alias = {
  77. ...config.resolve.alias,
  78. '../css/css$': resolve('src/common/ui/codemirror-ovr/css.js'),
  79. };
  80. (config.ignoreWarnings ??= []).push({
  81. // suppressing a false warning (the HTML spec allows it) as we don't need SSR
  82. message: /<tr> cannot be child of <table>/,
  83. });
  84. }),
  85. buildConfig('injected', './src/injected', (config) => {
  86. config.plugins.push(new ProtectWebpackBootstrapPlugin());
  87. addWrapperWithGlobals('injected/content', config, defsObj, getGlobals => ({
  88. header: () => `${skipReinjectionHeader} { ${getGlobals()}`,
  89. footer: '}}',
  90. }));
  91. }),
  92. buildConfig('injected-web', './src/injected/web', (config) => {
  93. config.output.libraryTarget = 'commonjs2';
  94. config.plugins.push(new ProtectWebpackBootstrapPlugin());
  95. addWrapperWithGlobals('injected/web', config, defsObj, getGlobals => ({
  96. header: () => `${skipReinjectionHeader}
  97. window[INIT_FUNC_NAME] = function (IS_FIREFOX,${PAGE_MODE_HANDSHAKE},${VAULT_ID}) {
  98. const module = { __proto__: null };
  99. ${getGlobals()}`,
  100. footer: `
  101. const { exports } = module;
  102. return exports.__esModule ? exports.default : exports;
  103. }};0;`,
  104. }));
  105. }),
  106. ];