webpack.config.base.js 4.5 KB

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