webpack.config.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. ],
  55. 'images': [
  56. 'image-chooser',
  57. 'image-chooser-telepath',
  58. ],
  59. 'documents': [
  60. 'document-chooser',
  61. 'document-chooser-telepath',
  62. ],
  63. 'snippets': [
  64. 'snippet-chooser',
  65. 'snippet-chooser-telepath',
  66. ],
  67. 'contrib/table_block': [
  68. 'table',
  69. ],
  70. 'contrib/typed_table_block': [
  71. 'typed_table_block',
  72. ],
  73. };
  74. const entry = {};
  75. for (const [appName, moduleNames] of Object.entries(entrypoints)) {
  76. moduleNames.forEach(moduleName => {
  77. entry[moduleName] = {
  78. import: [`./client/src/entrypoints/${appName}/${moduleName}.js`],
  79. filename: getOutputPath(appName, moduleName) + '.js',
  80. };
  81. // Add polyfills to all bundles except userbar
  82. // polyfills.js imports from node_modules, which adds a dependency on vendor.js (produced by splitChunks)
  83. // Because userbar is supposed to run on peoples frontends, we code it using portable JS so we don't need
  84. // to pull in all the additional JS that the vendor bundle has (such as React).
  85. if (moduleName !== 'userbar') {
  86. entry[moduleName].import.push('./client/src/utils/polyfills.js');
  87. }
  88. });
  89. }
  90. return {
  91. entry: entry,
  92. output: {
  93. path: path.resolve('.'),
  94. publicPath: '/static/js/'
  95. },
  96. resolve: {
  97. extensions: ['.ts', '.tsx', '.js'],
  98. // Some libraries import Node modules but don't use them in the browser.
  99. // Tell Webpack to provide empty mocks for them so importing them works.
  100. fallback: {
  101. fs: false,
  102. net: false,
  103. tls: false,
  104. },
  105. },
  106. externals: {
  107. jquery: 'jQuery',
  108. },
  109. module: {
  110. rules: [
  111. {
  112. test: /\.(js|ts)x?$/,
  113. loader: 'ts-loader',
  114. exclude: /node_modules/,
  115. },
  116. ].concat(Object.keys(exposedDependencies).map((name) => {
  117. const globalName = exposedDependencies[name];
  118. // Create expose-loader configs for each Wagtail dependency.
  119. return {
  120. test: require.resolve(name),
  121. use: [
  122. {
  123. loader: 'expose-loader',
  124. options: {
  125. exposes: {
  126. globalName,
  127. override: true
  128. }
  129. },
  130. },
  131. ],
  132. };
  133. }))
  134. },
  135. optimization: {
  136. splitChunks: {
  137. cacheGroups: {
  138. vendor: {
  139. name: getOutputPath('admin', 'vendor'),
  140. chunks: 'initial',
  141. minChunks: 2,
  142. reuseExistingChunk: true,
  143. },
  144. },
  145. },
  146. },
  147. // See https://webpack.js.org/configuration/devtool/.
  148. devtool: 'source-map',
  149. // For development mode only.
  150. watchOptions: {
  151. poll: 1000,
  152. aggregateTimeout: 300,
  153. },
  154. // Disable performance hints – currently there are much more valuable
  155. // optimizations for us to do outside of Webpack
  156. performance: {
  157. hints: false
  158. },
  159. stats: {
  160. // Add chunk information (setting this to `false` allows for a less verbose output)
  161. chunks: false,
  162. // Add the hash of the compilation
  163. hash: false,
  164. // `webpack --colors` equivalent
  165. colors: true,
  166. // Add information about the reasons why modules are included
  167. reasons: false,
  168. // Add webpack version information
  169. version: false,
  170. },
  171. };
  172. };