next
Version:
The React Framework
149 lines (148 loc) • 7.88 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectedClientEntries = void 0;
var _querystring = require("querystring");
var _webpack = require("next/dist/compiled/webpack/webpack");
var _constants = require("../../../shared/lib/constants");
var _utils = require("../loaders/utils");
var _normalizePagePath = require("../../../shared/lib/page-path/normalize-page-path");
var _denormalizePagePath = require("../../../shared/lib/page-path/denormalize-page-path");
var _onDemandEntryHandler = require("../../../server/dev/on-demand-entry-handler");
var _getPageStaticInfo = require("../../analysis/get-page-static-info");
var _constants1 = require("../../../lib/constants");
const PLUGIN_NAME = "ClientEntryPlugin";
const injectedClientEntries = new Map();
exports.injectedClientEntries = injectedClientEntries;
const regexCSS = /\.css$/;
class FlightClientEntryPlugin {
dev = false;
constructor(options){
if (typeof options.dev === "boolean") {
this.dev = options.dev;
}
this.isEdgeServer = options.isEdgeServer;
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory })=>{
compilation.dependencyFactories.set(_webpack.webpack.dependencies.ModuleDependency, normalModuleFactory);
compilation.dependencyTemplates.set(_webpack.webpack.dependencies.ModuleDependency, new _webpack.webpack.dependencies.NullDependency.Template());
});
compiler.hooks.finishMake.tapPromise(PLUGIN_NAME, (compilation)=>{
return this.createClientEndpoints(compilation);
});
}
async createClientEndpoints(compilation) {
const context = this.context;
const promises = [];
// For each SC server compilation entry, we need to create its corresponding
// client component entry.
for (const [name, entry] of compilation.entries.entries()){
var ref2, ref1;
// Check if the page entry is a server component or not.
const entryDependency = (ref2 = entry.dependencies) == null ? void 0 : ref2[0];
const request = entryDependency == null ? void 0 : entryDependency.request;
if (request && ((ref1 = entry.options) == null ? void 0 : ref1.layer) === "sc_server") {
const visited = new Set();
const clientComponentImports = [];
function filterClientComponents(dependency) {
var ref;
const mod = compilation.moduleGraph.getResolvedModule(dependency);
if (!mod) return;
// Keep client imports as simple
// native or installed js module: -> raw request, e.g. next/head
// client js or css: -> user request
const rawRequest = mod.rawRequest || "";
const modRequest = !rawRequest.endsWith(".css") && !rawRequest.startsWith(".") && !rawRequest.startsWith("/") ? rawRequest : (ref = mod.resourceResolveData) == null ? void 0 : ref.path;
if (!modRequest || visited.has(modRequest)) return;
visited.add(modRequest);
if (_utils.clientComponentRegex.test(modRequest) || regexCSS.test(modRequest)) {
clientComponentImports.push(modRequest);
}
compilation.moduleGraph.getOutgoingConnections(mod).forEach((connection)=>{
filterClientComponents(connection.dependency);
});
}
// Traverse the module graph to find all client components.
filterClientComponents(entryDependency);
const entryModule = compilation.moduleGraph.getResolvedModule(entryDependency);
const routeInfo = entryModule.buildInfo.route || {
page: (0, _denormalizePagePath).denormalizePagePath(name.replace(/^pages/, "")),
absolutePagePath: entryModule.resource
};
// Parse gSSP and gSP exports from the page source.
const pageStaticInfo = this.isEdgeServer ? {} : await (0, _getPageStaticInfo).getPageStaticInfo({
pageFilePath: routeInfo.absolutePagePath,
nextConfig: {},
isDev: this.dev
});
const loaderOptions = {
modules: clientComponentImports,
runtime: this.isEdgeServer ? _constants1.SERVER_RUNTIME.edge : _constants1.SERVER_RUNTIME.nodejs,
ssr: pageStaticInfo.ssr,
// Adding name here to make the entry key unique.
name
};
const clientLoader = `next-flight-client-entry-loader?${(0, _querystring).stringify(loaderOptions)}!`;
const clientSSRLoader = `next-flight-client-entry-loader?${(0, _querystring).stringify({
...loaderOptions,
server: true
})}!`;
const bundlePath = "app" + (0, _normalizePagePath).normalizePagePath(routeInfo.page);
// Inject the entry to the client compiler.
if (this.dev) {
const pageKey = "client" + routeInfo.page;
if (!_onDemandEntryHandler.entries[pageKey]) {
_onDemandEntryHandler.entries[pageKey] = {
bundlePath,
absolutePagePath: routeInfo.absolutePagePath,
clientLoader,
dispose: false,
lastActiveTime: Date.now()
};
const invalidator = (0, _onDemandEntryHandler).getInvalidator();
if (invalidator) {
invalidator.invalidate();
}
}
} else {
injectedClientEntries.set(bundlePath, `next-client-pages-loader?${(0, _querystring).stringify({
isServerComponent: true,
page: (0, _denormalizePagePath).denormalizePagePath(bundlePath.replace(/^pages/, "")),
absolutePagePath: clientLoader
})}!` + clientLoader);
}
// Inject the entry to the server compiler (__sc_client__).
const clientComponentEntryDep = _webpack.webpack.EntryPlugin.createDependency(clientSSRLoader, {
name: name + _constants.NEXT_CLIENT_SSR_ENTRY_SUFFIX
});
promises.push(new Promise((res, rej)=>{
compilation.addEntry(context, clientComponentEntryDep, this.isEdgeServer ? {
name: name + _constants.NEXT_CLIENT_SSR_ENTRY_SUFFIX,
library: {
name: [
"self._CLIENT_ENTRY"
],
type: "assign"
},
runtime: _constants.EDGE_RUNTIME_WEBPACK,
asyncChunks: false
} : {
name: name + _constants.NEXT_CLIENT_SSR_ENTRY_SUFFIX,
runtime: "webpack-runtime"
}, (err)=>{
if (err) {
rej(err);
} else {
res();
}
});
}));
}
}
await Promise.all(promises);
}
}
exports.FlightClientEntryPlugin = FlightClientEntryPlugin;
//# sourceMappingURL=flight-client-entry-plugin.js.map
;