webpack.config.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /* eslint-env node */
  2. /* eslint import/no-nodejs-modules:0 */
  3. import path from 'path';
  4. import webpack from 'webpack';
  5. import appConfig from '../../webpack.config';
  6. const staticPath = path.resolve(__dirname, '..', '..', 'static', 'app');
  7. const docsUiPath = path.resolve(__dirname, '..');
  8. /**
  9. * Default the config parameter that storybook passes into our webpack config
  10. * to an empty object specifically for eslint, since it will load this config
  11. * without passing in a config object.
  12. */
  13. const emptyConfig: webpack.Configuration = {
  14. module: {rules: []},
  15. resolve: {alias: {}, extensions: []},
  16. plugins: [],
  17. };
  18. type Opts = {
  19. config: webpack.Configuration;
  20. };
  21. const configBuilder = ({config}: Opts = {config: emptyConfig}) => {
  22. const [firstRule, ...rules] = (config.module?.rules ?? []) as webpack.RuleSetRule[];
  23. const filteredRules = rules.filter(rule => {
  24. const isFileLoader = !!rule?.loader?.includes('file-loader');
  25. const isPostCssLoader =
  26. Array.isArray(rule.use) &&
  27. rule.use.find(
  28. use => typeof use === 'object' && use?.loader?.includes('postcss-loader')
  29. );
  30. return !isFileLoader && !isPostCssLoader;
  31. });
  32. const extensions = new Set([
  33. ...(config.resolve?.extensions ?? []),
  34. ...(appConfig.resolve?.extensions ?? []),
  35. ]);
  36. const newConfig: webpack.Configuration = {
  37. ...config,
  38. module: {
  39. ...config.module,
  40. rules: [
  41. {
  42. ...firstRule,
  43. test: /\.(mjs|[tj]sx?)$/,
  44. include: [staticPath, docsUiPath],
  45. },
  46. {
  47. test: /\.less$/,
  48. use: ['style-loader', 'css-loader', 'less-loader'],
  49. },
  50. {
  51. test: /\.pegjs/,
  52. use: {loader: 'pegjs-loader'},
  53. },
  54. {
  55. test: /\.(woff|woff2|ttf|eot|svg|png|gif|ico|jpg)($|\?)/,
  56. type: 'asset/resource',
  57. },
  58. {
  59. test: /\.po$/,
  60. use: {
  61. loader: 'po-catalog-loader',
  62. options: {
  63. referenceExtensions: ['.js', '.jsx'],
  64. domain: 'sentry',
  65. },
  66. },
  67. },
  68. ...filteredRules,
  69. ],
  70. },
  71. plugins: [
  72. ...(config.plugins ?? []),
  73. new webpack.ProvidePlugin({jQuery: 'jquery'}),
  74. new webpack.DefinePlugin({'process.env.FIXED_DYNAMIC_CONTENT': true}),
  75. ],
  76. resolve: {
  77. ...config.resolve,
  78. extensions: Array.from(extensions),
  79. alias: {
  80. ...config.resolve?.alias,
  81. ...appConfig.resolve?.alias,
  82. 'docs-ui': docsUiPath,
  83. },
  84. fallback: {
  85. ...appConfig.resolve?.fallback,
  86. // XXX(epurkhiser): As per [0] assert is required for
  87. // @storybook/addons-docs, but seems we can just noop the polyfill.
  88. //
  89. // [0]: https://gist.github.com/shilman/8856ea1786dcd247139b47b270912324#gistcomment-3681971
  90. assert: false,
  91. },
  92. },
  93. };
  94. return newConfig;
  95. };
  96. export default configBuilder;