next.config.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /**
  2. * == Notes for production build==
  3. * The modules required from this file must be transpiled before running `next build`.
  4. *
  5. * See: https://github.com/vercel/next.js/discussions/35969#discussioncomment-2522954
  6. */
  7. const { withSuperjson } = require('next-superjson');
  8. const { PHASE_PRODUCTION_BUILD, PHASE_PRODUCTION_SERVER } = require('next/constants');
  9. // define additional entries
  10. const additionalWebpackEntries = {
  11. boot: './src/client/boot',
  12. };
  13. const setupTranspileModules = () => {
  14. const eazyLogger = require('eazy-logger');
  15. const { listScopedPackages, listPrefixedPackages } = require('./src/utils/next.config.utils');
  16. // setup logger
  17. const logger = eazyLogger.Logger({
  18. prefix: '[{green:next.config.js}] ',
  19. useLevelPrefixes: false,
  20. });
  21. // define transpiled packages for '@growi/*'
  22. const packages = [
  23. ...listScopedPackages(['@growi'], { ignorePackageNames: ['@growi/app'] }),
  24. // listing ESM packages until experimental.esmExternals works correctly to avoid ERR_REQUIRE_ESM
  25. 'react-markdown',
  26. 'unified',
  27. 'comma-separated-tokens',
  28. 'decode-named-character-reference',
  29. 'html-void-elements',
  30. 'property-information',
  31. 'space-separated-tokens',
  32. 'trim-lines',
  33. 'web-namespaces',
  34. 'vfile',
  35. 'zwitch',
  36. 'emoticon',
  37. 'direction', // for hast-util-select
  38. 'bcp-47-match', // for hast-util-select
  39. ...listPrefixedPackages(['remark-', 'rehype-', 'hast-', 'mdast-', 'micromark-', 'micromark-', 'unist-']),
  40. ];
  41. logger.info('{bold:Listing scoped packages for transpiling:}');
  42. logger.unprefixed('info', `{grey:${JSON.stringify(packages, null, 2)}}`);
  43. return require('next-transpile-modules')(packages);
  44. };
  45. module.exports = async(phase, { defaultConfig }) => {
  46. const { i18n, localePath } = require('./config/next-i18next.config');
  47. /** @type {import('next').NextConfig} */
  48. const nextConfig = {
  49. // == DOES NOT WORK
  50. // see: https://github.com/vercel/next.js/discussions/27876
  51. // experimental: { esmExternals: true }, // Prefer loading of ES Modules over CommonJS
  52. reactStrictMode: true,
  53. swcMinify: true,
  54. typescript: {
  55. tsconfigPath: 'tsconfig.build.client.json',
  56. },
  57. pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],
  58. i18n,
  59. /** @param config {import('next').NextConfig} */
  60. webpack(config, options) {
  61. // Avoid "Module not found: Can't resolve 'fs'"
  62. // See: https://stackoverflow.com/a/68511591
  63. if (!options.isServer) {
  64. config.resolve.fallback.fs = false;
  65. }
  66. // See: https://webpack.js.org/configuration/externals/
  67. // This provides a way of excluding dependencies from the output bundles
  68. config.externals.push('dtrace-provider');
  69. config.externals.push('mongoose');
  70. // configure additional entries
  71. const orgEntry = config.entry;
  72. config.entry = () => {
  73. return orgEntry().then((entry) => {
  74. return { ...entry, ...additionalWebpackEntries };
  75. });
  76. };
  77. const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
  78. config.plugins.push(
  79. new WebpackManifestPlugin({
  80. fileName: 'custom-manifest.json',
  81. }),
  82. );
  83. // setup i18next-hmr
  84. if (!options.isServer && options.dev) {
  85. const { I18NextHMRPlugin } = require('i18next-hmr/plugin');
  86. config.plugins.push(new I18NextHMRPlugin({ localesDir: localePath }));
  87. }
  88. return config;
  89. },
  90. };
  91. // production server
  92. if (phase === PHASE_PRODUCTION_SERVER) {
  93. return withSuperjson()(nextConfig);
  94. }
  95. const withTM = setupTranspileModules();
  96. const withBundleAnalyzer = require('@next/bundle-analyzer')({
  97. enabled: phase === PHASE_PRODUCTION_BUILD || process.env.ANALYZE === 'true',
  98. });
  99. return withBundleAnalyzer(withTM(withSuperjson()(nextConfig)));
  100. };