build-manifest-plugin.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.getEntrypointFiles = getEntrypointFiles;
  6. exports.default = void 0;
  7. var _devalue = _interopRequireDefault(require("next/dist/compiled/devalue"));
  8. var _webpack = require("next/dist/compiled/webpack/webpack");
  9. var _constants = require("../../../shared/lib/constants");
  10. var _getRouteFromEntrypoint = _interopRequireDefault(require("../../../server/get-route-from-entrypoint"));
  11. var _nextDropClientPagePlugin = require("./next-drop-client-page-plugin");
  12. var _utils = require("../../../shared/lib/router/utils");
  13. var _profilingPlugin = require("./profiling-plugin");
  14. class BuildManifestPlugin {
  15. constructor(options){
  16. this.buildId = options.buildId;
  17. this.isDevFallback = !!options.isDevFallback;
  18. this.rewrites = {
  19. beforeFiles: [],
  20. afterFiles: [],
  21. fallback: []
  22. };
  23. this.appDirEnabled = options.appDirEnabled;
  24. this.rewrites.beforeFiles = options.rewrites.beforeFiles.map(processRoute);
  25. this.rewrites.afterFiles = options.rewrites.afterFiles.map(processRoute);
  26. this.rewrites.fallback = options.rewrites.fallback.map(processRoute);
  27. this.exportRuntime = !!options.exportRuntime;
  28. }
  29. createAssets(compiler, compilation, assets) {
  30. const compilationSpan = _profilingPlugin.spans.get(compilation) || _profilingPlugin.spans.get(compiler);
  31. const createAssetsSpan = compilationSpan == null ? void 0 : compilationSpan.traceChild("NextJsBuildManifest-createassets");
  32. return createAssetsSpan == null ? void 0 : createAssetsSpan.traceFn(()=>{
  33. const entrypoints = compilation.entrypoints;
  34. const assetMap = {
  35. polyfillFiles: [],
  36. devFiles: [],
  37. ampDevFiles: [],
  38. lowPriorityFiles: [],
  39. rootMainFiles: [],
  40. pages: {
  41. "/_app": []
  42. },
  43. ampFirstPages: []
  44. };
  45. const ampFirstEntryNames = _nextDropClientPagePlugin.ampFirstEntryNamesMap.get(compilation);
  46. if (ampFirstEntryNames) {
  47. for (const entryName of ampFirstEntryNames){
  48. const pagePath = (0, _getRouteFromEntrypoint).default(entryName);
  49. if (!pagePath) {
  50. continue;
  51. }
  52. assetMap.ampFirstPages.push(pagePath);
  53. }
  54. }
  55. const mainFiles = new Set(getEntrypointFiles(entrypoints.get(_constants.CLIENT_STATIC_FILES_RUNTIME_MAIN)));
  56. if (this.appDirEnabled) {
  57. assetMap.rootMainFiles = [
  58. ...new Set(getEntrypointFiles(entrypoints.get(_constants.CLIENT_STATIC_FILES_RUNTIME_MAIN_APP))),
  59. ];
  60. }
  61. const compilationAssets = compilation.getAssets();
  62. assetMap.polyfillFiles = compilationAssets.filter((p)=>{
  63. // Ensure only .js files are passed through
  64. if (!p.name.endsWith(".js")) {
  65. return false;
  66. }
  67. return p.info && _constants.CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL in p.info;
  68. }).map((v)=>v.name);
  69. assetMap.devFiles = getEntrypointFiles(entrypoints.get(_constants.CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH)).filter((file)=>!mainFiles.has(file));
  70. assetMap.ampDevFiles = getEntrypointFiles(entrypoints.get(_constants.CLIENT_STATIC_FILES_RUNTIME_AMP));
  71. const systemEntrypoints = new Set([
  72. _constants.CLIENT_STATIC_FILES_RUNTIME_MAIN,
  73. _constants.CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH,
  74. _constants.CLIENT_STATIC_FILES_RUNTIME_AMP,
  75. ...this.appDirEnabled ? [
  76. _constants.CLIENT_STATIC_FILES_RUNTIME_MAIN_APP
  77. ] : [],
  78. ]);
  79. for (const entrypoint of compilation.entrypoints.values()){
  80. if (systemEntrypoints.has(entrypoint.name)) continue;
  81. const pagePath = (0, _getRouteFromEntrypoint).default(entrypoint.name);
  82. if (!pagePath) {
  83. continue;
  84. }
  85. const filesForPage = getEntrypointFiles(entrypoint);
  86. assetMap.pages[pagePath] = [
  87. ...new Set([
  88. ...mainFiles,
  89. ...filesForPage
  90. ])
  91. ];
  92. }
  93. if (!this.isDevFallback) {
  94. // Add the runtime build manifest file (generated later in this file)
  95. // as a dependency for the app. If the flag is false, the file won't be
  96. // downloaded by the client.
  97. assetMap.lowPriorityFiles.push(`${_constants.CLIENT_STATIC_FILES_PATH}/${this.buildId}/_buildManifest.js`);
  98. // Add the runtime ssg manifest file as a lazy-loaded file dependency.
  99. // We also stub this file out for development mode (when it is not
  100. // generated).
  101. const srcEmptySsgManifest = `self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()`;
  102. const ssgManifestPath = `${_constants.CLIENT_STATIC_FILES_PATH}/${this.buildId}/_ssgManifest.js`;
  103. assetMap.lowPriorityFiles.push(ssgManifestPath);
  104. assets[ssgManifestPath] = new _webpack.sources.RawSource(srcEmptySsgManifest);
  105. }
  106. assetMap.pages = Object.keys(assetMap.pages).sort()// eslint-disable-next-line
  107. .reduce((a, c)=>(a[c] = assetMap.pages[c], a), {});
  108. let buildManifestName = _constants.BUILD_MANIFEST;
  109. if (this.isDevFallback) {
  110. buildManifestName = `fallback-${_constants.BUILD_MANIFEST}`;
  111. }
  112. assets[buildManifestName] = new _webpack.sources.RawSource(JSON.stringify(assetMap, null, 2));
  113. if (this.exportRuntime) {
  114. assets[`server/${_constants.MIDDLEWARE_BUILD_MANIFEST}.js`] = new _webpack.sources.RawSource(`self.__BUILD_MANIFEST=${JSON.stringify(assetMap)}`);
  115. }
  116. if (!this.isDevFallback) {
  117. const clientManifestPath = `${_constants.CLIENT_STATIC_FILES_PATH}/${this.buildId}/_buildManifest.js`;
  118. assets[clientManifestPath] = new _webpack.sources.RawSource(`self.__BUILD_MANIFEST = ${generateClientManifest(compiler, compilation, assetMap, this.rewrites)};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()`);
  119. }
  120. return assets;
  121. });
  122. }
  123. apply(compiler) {
  124. compiler.hooks.make.tap("NextJsBuildManifest", (compilation)=>{
  125. // @ts-ignore TODO: Remove ignore when webpack 5 is stable
  126. compilation.hooks.processAssets.tap({
  127. name: "NextJsBuildManifest",
  128. // @ts-ignore TODO: Remove ignore when webpack 5 is stable
  129. stage: _webpack.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
  130. }, (assets)=>{
  131. this.createAssets(compiler, compilation, assets);
  132. });
  133. });
  134. return;
  135. }
  136. }
  137. exports.default = BuildManifestPlugin;
  138. function _interopRequireDefault(obj) {
  139. return obj && obj.__esModule ? obj : {
  140. default: obj
  141. };
  142. }
  143. // This function takes the asset map generated in BuildManifestPlugin and creates a
  144. // reduced version to send to the client.
  145. function generateClientManifest(compiler, compilation, assetMap, rewrites) {
  146. const compilationSpan = _profilingPlugin.spans.get(compilation) || _profilingPlugin.spans.get(compiler);
  147. const genClientManifestSpan = compilationSpan == null ? void 0 : compilationSpan.traceChild("NextJsBuildManifest-generateClientManifest");
  148. return genClientManifestSpan == null ? void 0 : genClientManifestSpan.traceFn(()=>{
  149. const clientManifest = {
  150. // TODO: update manifest type to include rewrites
  151. __rewrites: rewrites
  152. };
  153. const appDependencies = new Set(assetMap.pages["/_app"]);
  154. const sortedPageKeys = (0, _utils).getSortedRoutes(Object.keys(assetMap.pages));
  155. sortedPageKeys.forEach((page)=>{
  156. const dependencies = assetMap.pages[page];
  157. if (page === "/_app") return;
  158. // Filter out dependencies in the _app entry, because those will have already
  159. // been loaded by the client prior to a navigation event
  160. const filteredDeps = dependencies.filter((dep)=>!appDependencies.has(dep));
  161. // The manifest can omit the page if it has no requirements
  162. if (filteredDeps.length) {
  163. clientManifest[page] = filteredDeps;
  164. }
  165. });
  166. // provide the sorted pages as an array so we don't rely on the object's keys
  167. // being in order and we don't slow down look-up time for page assets
  168. clientManifest.sortedPages = sortedPageKeys;
  169. return (0, _devalue).default(clientManifest);
  170. });
  171. }
  172. function getEntrypointFiles(entrypoint) {
  173. var ref;
  174. return (ref = entrypoint == null ? void 0 : entrypoint.getFiles().filter((file)=>{
  175. // We don't want to include `.hot-update.js` files into the initial page
  176. return /(?<!\.hot-update)\.(js|css)($|\?)/.test(file);
  177. }).map((file)=>file.replace(/\\/g, "/"))) != null ? ref : [];
  178. }
  179. const processRoute = (r)=>{
  180. const rewrite = {
  181. ...r
  182. };
  183. // omit external rewrite destinations since these aren't
  184. // handled client-side
  185. if (!rewrite.destination.startsWith("/")) {
  186. delete rewrite.destination;
  187. }
  188. return rewrite;
  189. };
  190. //# sourceMappingURL=build-manifest-plugin.js.map