next.config.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 path = require('path');
  8. const { withSuperjson } = require('next-superjson');
  9. const { PHASE_PRODUCTION_BUILD, PHASE_PRODUCTION_SERVER } = require('next/constants');
  10. const getTranspilePackages = () => {
  11. const { listPrefixedPackages } = require('./src/utils/next.config.utils');
  12. const packages = [
  13. // listing ESM packages until experimental.esmExternals works correctly to avoid ERR_REQUIRE_ESM
  14. 'react-markdown',
  15. 'unified',
  16. 'markdown-table',
  17. 'bail',
  18. 'ccount',
  19. 'character-entities',
  20. 'character-entities-html4',
  21. 'character-entities-legacy',
  22. 'comma-separated-tokens',
  23. 'decode-named-character-reference',
  24. 'devlop',
  25. 'fault',
  26. 'escape-string-regexp',
  27. 'hastscript',
  28. 'html-void-elements',
  29. 'is-absolute-url',
  30. 'is-plain-obj',
  31. 'longest-streak',
  32. 'micromark',
  33. 'property-information',
  34. 'space-separated-tokens',
  35. 'stringify-entities',
  36. 'trim-lines',
  37. 'trough',
  38. 'web-namespaces',
  39. 'vfile',
  40. 'vfile-location',
  41. 'vfile-message',
  42. 'zwitch',
  43. 'emoticon',
  44. 'direction', // for hast-util-select
  45. 'bcp-47-match', // for hast-util-select
  46. ...listPrefixedPackages(['remark-', 'rehype-', 'hast-', 'mdast-', 'micromark-', 'unist-']),
  47. ];
  48. // const eazyLogger = require('eazy-logger');
  49. // const logger = eazyLogger.Logger({
  50. // prefix: '[{green:next.config.js}] ',
  51. // useLevelPrefixes: false,
  52. // });
  53. // logger.info('{bold:Listing scoped packages for transpiling:}');
  54. // logger.unprefixed('info', `{grey:${JSON.stringify(packages, null, 2)}}`);
  55. return packages;
  56. };
  57. const optimizePackageImports = [
  58. '@growi/core',
  59. '@growi/editor',
  60. '@growi/pluginkit',
  61. '@growi/presentation',
  62. '@growi/preset-themes',
  63. '@growi/remark-attachment-refs',
  64. '@growi/remark-drawio',
  65. '@growi/remark-growi-directive',
  66. '@growi/remark-lsx',
  67. '@growi/slack',
  68. '@growi/ui',
  69. ];
  70. module.exports = async(phase, { defaultConfig }) => {
  71. const { i18n, localePath } = require('./config/next-i18next.config');
  72. /** @type {import('next').NextConfig} */
  73. const nextConfig = {
  74. reactStrictMode: true,
  75. poweredByHeader: false,
  76. pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],
  77. i18n,
  78. // for build
  79. eslint: {
  80. ignoreDuringBuilds: true,
  81. },
  82. typescript: {
  83. tsconfigPath: 'tsconfig.build.client.json',
  84. },
  85. transpilePackages: phase !== PHASE_PRODUCTION_SERVER
  86. ? getTranspilePackages()
  87. : undefined,
  88. experimental: {
  89. optimizePackageImports,
  90. },
  91. /** @param config {import('next').NextConfig} */
  92. webpack(config, options) {
  93. if (!options.isServer) {
  94. // Avoid "Module not found: Can't resolve 'fs'"
  95. // See: https://stackoverflow.com/a/68511591
  96. config.resolve.fallback.fs = false;
  97. // exclude packages from the output bundles
  98. config.module.rules.push(
  99. ...[
  100. /dtrace-provider/,
  101. /mongoose/,
  102. /mathjax-full/, // required from marp
  103. ].map((packageRegExp) => {
  104. return {
  105. test: packageRegExp,
  106. use: 'null-loader',
  107. };
  108. }),
  109. );
  110. }
  111. // extract sourcemap
  112. if (options.dev) {
  113. config.module.rules.push({
  114. test: /.(c|m)?js$/,
  115. exclude: [/node_modules/, path.resolve(__dirname)],
  116. enforce: 'pre',
  117. use: ['source-map-loader'],
  118. });
  119. }
  120. // setup i18next-hmr
  121. if (!options.isServer && options.dev) {
  122. const { I18NextHMRPlugin } = require('i18next-hmr/webpack');
  123. config.plugins.push(new I18NextHMRPlugin({ localesDir: localePath }));
  124. }
  125. return config;
  126. },
  127. };
  128. // production server
  129. if (phase === PHASE_PRODUCTION_SERVER) {
  130. return withSuperjson()(nextConfig);
  131. }
  132. const withBundleAnalyzer = require('@next/bundle-analyzer')({
  133. enabled: phase === PHASE_PRODUCTION_BUILD && process.env.ANALYZE === 'true',
  134. });
  135. return withBundleAnalyzer(withSuperjson()(nextConfig));
  136. };