webpack.config.base.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. const fs = require('fs');
  2. const path = require('path');
  3. const webpack = require('webpack');
  4. const TerserPlugin = require('terser-webpack-plugin');
  5. const WrapperPlugin = require('wrapper-webpack-plugin');
  6. const electronRoot = path.resolve(__dirname, '../..');
  7. class AccessDependenciesPlugin {
  8. apply (compiler) {
  9. compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
  10. compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
  11. const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p));
  12. console.info(JSON.stringify(filePaths));
  13. });
  14. });
  15. }
  16. }
  17. module.exports = ({
  18. alwaysHasNode,
  19. loadElectronFromAlternateTarget,
  20. targetDeletesNodeGlobals,
  21. target,
  22. wrapInitWithProfilingTimeout,
  23. wrapInitWithTryCatch
  24. }) => {
  25. let entry = path.resolve(electronRoot, 'lib', target, 'init.ts');
  26. if (!fs.existsSync(entry)) {
  27. entry = path.resolve(electronRoot, 'lib', target, 'init.js');
  28. }
  29. const electronAPIFile = path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts');
  30. return (env = {}, argv = {}) => {
  31. const onlyPrintingGraph = !!env.PRINT_WEBPACK_GRAPH;
  32. const outputFilename = argv['output-filename'] || `${target}.bundle.js`;
  33. const defines = {
  34. BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
  35. };
  36. if (env.buildflags) {
  37. const flagFile = fs.readFileSync(env.buildflags, 'utf8');
  38. for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
  39. const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/);
  40. if (flagMatch) {
  41. const [, flagName, flagValue] = flagMatch;
  42. defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
  43. }
  44. }
  45. }
  46. const ignoredModules = [];
  47. if (defines.ENABLE_DESKTOP_CAPTURER === 'false') {
  48. ignoredModules.push(
  49. '@electron/internal/browser/desktop-capturer',
  50. '@electron/internal/browser/api/desktop-capturer',
  51. '@electron/internal/renderer/api/desktop-capturer'
  52. );
  53. }
  54. if (defines.ENABLE_REMOTE_MODULE === 'false') {
  55. ignoredModules.push(
  56. '@electron/internal/browser/remote/server',
  57. '@electron/internal/renderer/api/remote'
  58. );
  59. }
  60. if (defines.ENABLE_VIEWS_API === 'false') {
  61. ignoredModules.push(
  62. '@electron/internal/browser/api/views/image-view.js'
  63. );
  64. }
  65. const plugins = [];
  66. if (onlyPrintingGraph) {
  67. plugins.push(new AccessDependenciesPlugin());
  68. }
  69. if (targetDeletesNodeGlobals) {
  70. plugins.push(new webpack.ProvidePlugin({
  71. process: ['@electron/internal/common/webpack-provider', 'process'],
  72. global: ['@electron/internal/common/webpack-provider', '_global'],
  73. Buffer: ['@electron/internal/common/webpack-provider', 'Buffer']
  74. }));
  75. }
  76. plugins.push(new webpack.ProvidePlugin({
  77. Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise']
  78. }));
  79. plugins.push(new webpack.DefinePlugin(defines));
  80. if (wrapInitWithProfilingTimeout) {
  81. plugins.push(new WrapperPlugin({
  82. header: 'function ___electron_webpack_init__() {',
  83. footer: `
  84. };
  85. if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
  86. setTimeout(___electron_webpack_init__, 0);
  87. } else {
  88. ___electron_webpack_init__();
  89. }`
  90. }));
  91. }
  92. if (wrapInitWithTryCatch) {
  93. plugins.push(new WrapperPlugin({
  94. header: 'try {',
  95. footer: `
  96. } catch (err) {
  97. console.error('Electron ${outputFilename} script failed to run');
  98. console.error(err);
  99. }`
  100. }));
  101. }
  102. return {
  103. mode: 'development',
  104. devtool: false,
  105. entry,
  106. target: alwaysHasNode ? 'node' : 'web',
  107. output: {
  108. filename: outputFilename
  109. },
  110. resolve: {
  111. alias: {
  112. '@electron/internal': path.resolve(electronRoot, 'lib'),
  113. electron$: electronAPIFile,
  114. 'electron/main$': electronAPIFile,
  115. 'electron/renderer$': electronAPIFile,
  116. 'electron/common$': electronAPIFile,
  117. // Force timers to resolve to our dependency that doesn't use window.postMessage
  118. timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
  119. },
  120. extensions: ['.ts', '.js']
  121. },
  122. module: {
  123. rules: [{
  124. test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
  125. loader: 'null-loader'
  126. }, {
  127. test: /\.ts$/,
  128. loader: 'ts-loader',
  129. options: {
  130. configFile: path.resolve(electronRoot, 'tsconfig.electron.json'),
  131. transpileOnly: onlyPrintingGraph,
  132. ignoreDiagnostics: [
  133. // File '{0}' is not under 'rootDir' '{1}'.
  134. 6059
  135. ]
  136. }
  137. }]
  138. },
  139. node: {
  140. __dirname: false,
  141. __filename: false,
  142. // We provide our own "timers" import above, any usage of setImmediate inside
  143. // one of our renderer bundles should import it from the 'timers' package
  144. setImmediate: false
  145. },
  146. optimization: {
  147. minimize: env.mode === 'production',
  148. minimizer: [
  149. new TerserPlugin({
  150. terserOptions: {
  151. keep_classnames: true,
  152. keep_fnames: true
  153. }
  154. })
  155. ]
  156. },
  157. plugins
  158. };
  159. };
  160. };