diff --git a/packages/plugin-vue/src/config/client.ts b/packages/plugin-vue/src/config/client.ts index 1a5c6534..c6b16454 100644 --- a/packages/plugin-vue/src/config/client.ts +++ b/packages/plugin-vue/src/config/client.ts @@ -4,8 +4,7 @@ import * as WebpackChain from 'webpack-chain' import { getBaseConfig } from './base' const safePostCssParser = require('postcss-safe-parser') -const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin -const generateAnalysis = Boolean(process.env.GENERATE_ANALYSIS) + const loadModule = loadModuleFromFramework const getClientWebpack = (chain: WebpackChain) => { @@ -60,10 +59,6 @@ const getClientWebpack = (chain: WebpackChain) => { fileName: 'asset-manifest.json' }]) - chain.when(generateAnalysis, chain => { - chain.plugin('analyze').use(BundleAnalyzerPlugin) - }) - chainClientConfig(chain) // 合并用户自定义配置 return chain.toConfig() diff --git a/packages/plugin-vue3/src/config/client.ts b/packages/plugin-vue3/src/config/client.ts index 3ddaa47f..0e54aed5 100644 --- a/packages/plugin-vue3/src/config/client.ts +++ b/packages/plugin-vue3/src/config/client.ts @@ -1,5 +1,6 @@ import { loadConfig, getOutputPublicPath, loadModuleFromFramework, getSplitChunksOptions, getBuildConfig, terserConfig, asyncChunkMap } from 'ssr-common-utils' import * as WebpackChain from 'webpack-chain' + import { getBaseConfig } from './base' const safePostCssParser = require('postcss-safe-parser') diff --git a/packages/plugin-vue3/src/entry/server-entry.ts b/packages/plugin-vue3/src/entry/server-entry.ts index 655b3d1a..e97b4838 100644 --- a/packages/plugin-vue3/src/entry/server-entry.ts +++ b/packages/plugin-vue3/src/entry/server-entry.ts @@ -16,7 +16,7 @@ const { FeRoutes, App, layoutFetch, Layout } = Routes const staticConfig = getStaticConfig() const serverRender = async (ctx: ISSRContext, config: IConfig) => { - const { mode, customeHeadScript, customeFooterScript, parallelFetch, prefix, isVite, isDev, clientPrefix, stream, fePort, https, rootId, bigpipe, hashRouter, asyncGlobalData } = config + const { mode, customeHeadScript, customeFooterScript, parallelFetch, prefix, isVite, isDev, clientPrefix, stream, rootId, bigpipe, hashRouter, asyncGlobalData } = config const store = createStore() const router = createRouter() const pinia = createPinia() @@ -40,7 +40,7 @@ const serverRender = async (ctx: ISSRContext, config: IConfig) => { }: vue3AppParams) => { const app = createSSRApp({ render: function () { - const ssrDevInfo = { manifest: isDev ? manifest : '', rootId, fePort: isDev ? fePort : '', https: isDev ? https : '' } + const ssrDevInfo = { manifest: isDev ? manifest : '', rootId } const innerHTML = splitPageInfo({ 'window.__USE_SSR__': !isCsr, 'window.__INITIAL_DATA__': isCsr ? {} : serialize(state), diff --git a/packages/utils/src/server/loadConfig.ts b/packages/utils/src/server/loadConfig.ts index 3704645b..221b56ed 100644 --- a/packages/utils/src/server/loadConfig.ts +++ b/packages/utils/src/server/loadConfig.ts @@ -151,9 +151,10 @@ const loadConfig = (): IConfig => { } const assetsDir = userConfig.assetsDir ?? 'static' const manifestPath = `${normalizeEndPath(devPublicPath)}asset-manifest.json` + const chunkMapPath = `${normalizeEndPath(devPublicPath)}chunkMap.json` const staticPath = `${normalizeEndPath(devPublicPath)}${assetsDir}` const hotUpdatePath = `${normalizeEndPath(devPublicPath)}*.hot-update**` - const proxyKey = [staticPath, hotUpdatePath, manifestPath] + const proxyKey = [staticPath, hotUpdatePath, manifestPath, chunkMapPath] const prefix = '/' const dynamicFile = { serverBundle: join(cwd, `./build/server/${chunkName}.server.js`), diff --git a/packages/utils/src/server/webpack/common-chain.ts b/packages/utils/src/server/webpack/common-chain.ts index 3e635c90..51bed162 100644 --- a/packages/utils/src/server/webpack/common-chain.ts +++ b/packages/utils/src/server/webpack/common-chain.ts @@ -10,6 +10,7 @@ import { logWarning } from '../log' import { getPkgMajorVersion } from '../judge' import { asyncChunkMap } from '../build-utils' import { nameSpaceBuiltinModules } from '../static' +import { FileToChunkRelationPlugin } from './plugins' const [antdVersion, vantVersion] = [getPkgMajorVersion('antd'), getPkgMajorVersion('vant')] const isAntd4 = antdVersion === 4 @@ -119,7 +120,7 @@ const addBabelLoader = (chain: Rule, envOptions: any, isServer: boolean) .end() } const addCommonChain = (chain: Chain, isServer: boolean) => { - const { babelOptions, corejsOptions, babelExtraModule, assetsDir, optimize } = loadConfig() + const { babelOptions, corejsOptions, babelExtraModule, assetsDir, optimize, isDev } = loadConfig() const { publicPath, imagePath } = getImageOutputPath() const envOptions = { modules: false, @@ -191,7 +192,9 @@ const addCommonChain = (chain: Chain, isServer: boolean) => { nameSpaceBuiltinModules.forEach(moduleName => { chain.node.set(moduleName, 'empty') }) - + chain.when(isDev, chain => { + chain.plugin('chunkMap').use(FileToChunkRelationPlugin) + }) chain.when(generateAnalysis, chain => { chain.plugin('analyze').use(BundleAnalyzerPlugin) }) diff --git a/packages/utils/src/server/webpack/plugins.ts b/packages/utils/src/server/webpack/plugins.ts new file mode 100644 index 00000000..63a25aec --- /dev/null +++ b/packages/utils/src/server/webpack/plugins.ts @@ -0,0 +1,41 @@ +import { relative } from 'path' +import type { Compiler } from 'webpack' + +interface FileToChunkMap { + [filePath: string]: string +} + +export class FileToChunkRelationPlugin { + apply (compiler: Compiler) { + compiler.hooks.emit.tapAsync( + 'FileToChunkRelationPlugin', + (compilation, callback) => { + const fileToChunkMap: FileToChunkMap = {} + + // Iterate through all chunks + for (const chunk of compilation.chunks) { + // Get all modules for this chunk + const chunkName = chunk.name || chunk.id as string + for (const module of chunk.modulesIterable) { + if (module.resource) { + let source = relative(compiler.context, module.resource) + if (!source.startsWith('.')) { + source = `./${source}` + } + fileToChunkMap[source] = chunkName + } + } + } + + // Add the map as a new asset + const content = JSON.stringify(fileToChunkMap, null, 2) + compilation.assets['chunkMap.json'] = { + source: () => content, + size: () => content.length + } + + callback() + } + ) + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1462af25..d572759f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5856,7 +5856,7 @@ packages: /axios/1.4.0: resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: - follow-redirects: 1.15.1 + follow-redirects: 1.15.1_debug@4.3.4 form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -10123,16 +10123,6 @@ packages: /fn.name/1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - /follow-redirects/1.15.1: - resolution: {integrity: sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: false - /follow-redirects/1.15.1_debug@4.3.4: resolution: {integrity: sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==} engines: {node: '>=4.0'}