webpack.config.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. const path = require('path');
  2. // Generates a path to the output bundle to be loaded in the browser.
  3. const getOutputPath = (app, filename) => {
  4. let appLabel = `wagtail${app}`;
  5. // Exceptions
  6. if (app === 'documents') {
  7. appLabel = 'wagtaildocs';
  8. } else if (app === 'contrib/table_block') {
  9. appLabel = 'table_block';
  10. } else if (app === 'contrib/typed_table_block') {
  11. appLabel = 'typed_table_block';
  12. }
  13. return path.join('wagtail', app, 'static', appLabel, 'js', filename);
  14. };
  15. // Mapping from package name to exposed global variable.
  16. const exposedDependencies = {
  17. 'focus-trap-react': 'FocusTrapReact',
  18. 'react': 'React',
  19. 'react-dom': 'ReactDOM',
  20. 'react-transition-group/CSSTransitionGroup': 'CSSTransitionGroup',
  21. 'draft-js': 'DraftJS',
  22. };
  23. module.exports = function exports() {
  24. const entrypoints = {
  25. 'admin': [
  26. 'collapsible',
  27. 'comments',
  28. 'core',
  29. 'date-time-chooser',
  30. 'draftail',
  31. 'expanding_formset',
  32. 'filtered-select',
  33. 'hallo-bootstrap',
  34. 'hallo-plugins/hallo-hr',
  35. 'hallo-plugins/hallo-requireparagraphs',
  36. 'hallo-plugins/hallo-wagtaillink',
  37. 'lock-unlock-action',
  38. 'modal-workflow',
  39. 'page-chooser-modal',
  40. 'page-chooser',
  41. 'page-editor',
  42. 'privacy-switch',
  43. 'sidebar',
  44. 'sidebar-legacy',
  45. 'task-chooser-modal',
  46. 'task-chooser',
  47. 'telepath/blocks',
  48. 'telepath/telepath',
  49. 'telepath/widgets',
  50. 'userbar',
  51. 'wagtailadmin',
  52. 'workflow-action',
  53. 'workflow-status',
  54. 'bulk-actions'
  55. ],
  56. 'images': [
  57. 'image-chooser',
  58. 'image-chooser-telepath',
  59. ],
  60. 'documents': [
  61. 'document-chooser',
  62. 'document-chooser-telepath',
  63. ],
  64. 'snippets': [
  65. 'snippet-chooser',
  66. 'snippet-chooser-telepath',
  67. ],
  68. 'contrib/table_block': [
  69. 'table',
  70. ],
  71. 'contrib/typed_table_block': [
  72. 'typed_table_block',
  73. ],
  74. };
  75. const entry = {};
  76. for (const [appName, moduleNames] of Object.entries(entrypoints)) {
  77. moduleNames.forEach(moduleName => {
  78. entry[moduleName] = {
  79. import: [`./client/src/entrypoints/${appName}/${moduleName}.js`],
  80. filename: getOutputPath(appName, moduleName) + '.js',
  81. };
  82. // Add polyfills to all bundles except userbar
  83. // polyfills.js imports from node_modules, which adds a dependency on vendor.js (produced by splitChunks)
  84. // Because userbar is supposed to run on peoples frontends, we code it using portable JS so we don't need
  85. // to pull in all the additional JS that the vendor bundle has (such as React).
  86. if (moduleName !== 'userbar') {
  87. entry[moduleName].import.push('./client/src/utils/polyfills.js');
  88. }
  89. });
  90. }
  91. return {
  92. entry: entry,
  93. output: {
  94. path: path.resolve('.'),
  95. publicPath: '/static/js/'
  96. },
  97. resolve: {
  98. extensions: ['.ts', '.tsx', '.js'],
  99. // Some libraries import Node modules but don't use them in the browser.
  100. // Tell Webpack to provide empty mocks for them so importing them works.
  101. fallback: {
  102. fs: false,
  103. net: false,
  104. tls: false,
  105. },
  106. },
  107. externals: {
  108. jquery: 'jQuery',
  109. },
  110. module: {
  111. rules: [
  112. {
  113. test: /\.(js|ts)x?$/,
  114. loader: 'ts-loader',
  115. exclude: /node_modules/,
  116. },
  117. ].concat(Object.keys(exposedDependencies).map((name) => {
  118. const globalName = exposedDependencies[name];
  119. // Create expose-loader configs for each Wagtail dependency.
  120. return {
  121. test: require.resolve(name),
  122. use: [
  123. {
  124. loader: 'expose-loader',
  125. options: {
  126. exposes: {
  127. globalName,
  128. override: true
  129. }
  130. },
  131. },
  132. ],
  133. };
  134. }))
  135. },
  136. optimization: {
  137. splitChunks: {
  138. cacheGroups: {
  139. vendor: {
  140. name: getOutputPath('admin', 'vendor'),
  141. chunks: 'initial',
  142. minChunks: 2,
  143. reuseExistingChunk: true,
  144. },
  145. },
  146. },
  147. },
  148. // See https://webpack.js.org/configuration/devtool/.
  149. devtool: 'source-map',
  150. // For development mode only.
  151. watchOptions: {
  152. poll: 1000,
  153. aggregateTimeout: 300,
  154. },
  155. // Disable performance hints – currently there are much more valuable
  156. // optimizations for us to do outside of Webpack
  157. performance: {
  158. hints: false
  159. },
  160. stats: {
  161. // Add chunk information (setting this to `false` allows for a less verbose output)
  162. chunks: false,
  163. // Add the hash of the compilation
  164. hash: false,
  165. // `webpack --colors` equivalent
  166. colors: true,
  167. // Add information about the reasons why modules are included
  168. reasons: false,
  169. // Add webpack version information
  170. version: false,
  171. },
  172. };
  173. };