in packages/ice/src/createService.ts [210:394]
defaultValue: getDefaultValue(),
};
}
return resetConfig;
});
ctx.registerConfig(configType, configData);
});
let taskConfigs: TaskConfig<Config>[] = await ctx.setup();
// get userConfig after setup because of userConfig maybe modified by plugins
const { userConfig } = ctx;
const { routes: routesConfig, server, syntaxFeatures, polyfill } = userConfig;
const coreEnvKeys = getCoreEnvKeys();
const routesInfo = await generateRoutesInfo(rootDir, routesConfig, routeManifest.getRoutesDefinitions());
routeManifest.setRoutes(routesInfo.routes);
const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('dataLoader');
const csr = !userConfig.ssr && !userConfig.ssg;
const disableRouter = (userConfig?.optimization?.router && routesInfo.routesCount <= 1) ||
userConfig?.optimization?.disableRouter;
if (disableRouter) {
logger.info('`optimization.router` is enabled, ice build will remove react-router and history which is unnecessary.');
taskConfigs = mergeTaskConfig(taskConfigs, {
alias: {
'@ice/runtime/router': '@ice/runtime/single-router',
},
});
} else {
// Only when router is enabled, we will add router polyfills.
addPolyfills(generatorAPI, userConfig.featurePolyfill, rootDir, command === 'start');
}
// Get first task config as default platform config.
const platformTaskConfig = taskConfigs[0];
const iceRuntimePath = '@ice/runtime';
// Only when code splitting use the default strategy or set to `router`, the router will be lazy loaded.
const lazy = [true, 'chunks', 'page', 'page-vendors'].includes(userConfig.codeSplitting);
const { routeImports, routeDefinition } = getRoutesDefinition({
manifest: routesInfo.routes,
lazy,
});
const loaderExports = hasExportAppData || Boolean(routesInfo.loaders);
const hasDataLoader = Boolean(userConfig.dataLoader) && loaderExports;
// add render data
generator.setRenderData({
...routesInfo,
target,
iceRuntimePath,
hasExportAppData,
runtimeModules,
coreEnvKeys,
// Stringify basename because `config` basename in task config only support type string.
basename: JSON.stringify(platformTaskConfig.config.basename || '/'),
memoryRouter: platformTaskConfig.config.memoryRouter,
hydrate: !csr,
importCoreJs: polyfill === 'entry',
// Enable react-router for web as default.
enableRoutes: true,
entryCode,
hasDocument: hasDocument(rootDir),
dataLoader: userConfig.dataLoader,
hasDataLoader,
routeImports,
routeDefinition,
routesFile: './routes',
});
dataCache.set('routes', JSON.stringify(routesInfo));
dataCache.set('hasExportAppData', hasExportAppData ? 'true' : '');
// Render exports files if route component export dataLoader / pageConfig.
renderExportsTemplate(
{
...routesInfo,
hasExportAppData,
},
generator.addRenderFile,
{
rootDir,
runtimeDir: RUNTIME_TMP_DIR,
templateDir: path.join(templateDir, 'exports'),
dataLoader: Boolean(userConfig.dataLoader),
},
);
if (platformTaskConfig.config.server?.fallbackEntry) {
// Add fallback entry for server side rendering.
generator.addRenderFile('core/entry.server.ts.ejs', FALLBACK_ENTRY, { hydrate: false });
}
if (typeof userConfig.dataLoader === 'object' && userConfig.dataLoader.fetcher) {
const {
packageName,
method,
} = userConfig.dataLoader.fetcher;
generatorAPI.addDataLoaderImport(method ? {
source: packageName,
alias: {
[method]: 'dataLoaderFetcher',
},
specifier: [method],
} : {
source: packageName,
specifier: '',
});
}
if (multipleServerEntry(userConfig, command)) {
renderMultiEntry({
generator,
renderRoutes: routeManifest.getFlattenRoute(),
routesManifest: routesInfo.routes,
lazy,
});
}
// render template before webpack compile
const renderStart = new Date().getTime();
generator.render();
logger.debug('template render cost:', new Date().getTime() - renderStart);
if (server.onDemand && command === 'start') {
serverRunner = new ServerRunner({
speedup: commandArgs.speedup,
rootDir,
task: platformTaskConfig,
server,
csr,
getRoutesFile: () => routeManifest.getRoutesFile(),
});
addWatchEvent([
// Files in .ice directory will update when routes changed.
/(src|.ice)\/?[\w*-:.$]+$/,
async (eventName: string, filePath: string) => {
if (eventName === 'change' || eventName === 'add') {
serverRunner.fileChanged(filePath);
}
}],
);
}
// create serverCompiler with task config
const serverCompiler = createServerCompiler({
rootDir,
task: platformTaskConfig,
command,
speedup: commandArgs.speedup,
server,
syntaxFeatures,
getRoutesFile: () => routeManifest.getRoutesFile(),
});
initAppConfigCompiler(serverCompiler);
initRouteConfigCompiler(serverCompiler);
addWatchEvent(
...getWatchEvents({
generator,
targetDir: RUNTIME_TMP_DIR,
templateDir: coreTemplate,
cache: dataCache,
routeManifest,
lazyRoutes: lazy,
ctx,
}),
);
const appConfig: AppConfig = (await getAppConfig()).default;
updateRuntimeEnv(appConfig, {
disableRouter,
// The optimization for runtime size should only be enabled in production mode.
routesConfig: command !== 'build' || routesInfo.routesExports.length > 0,
dataLoader: command !== 'build' || loaderExports,
});
return {
run: async () => {
const bundlerConfig = {
taskConfigs,
spinner: buildSpinner,
routeManifest,
appConfig,
hooksAPI: {