diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 9d17b245767fc1..ffea7931d02db6 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -271,6 +271,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { return { code: modulesCode || `export default ${JSON.stringify(css)}`, map: { mappings: '' }, + meta: { css: true }, // avoid the css module from being tree-shaken so that we can retrieve // it in renderChunk() moduleSideEffects: 'no-treeshake' diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 77b27feceddaec..2c072c4099993f 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -344,22 +344,40 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { // inject chunk asset links if (chunk) { - const assetTags = [ + const assetTags = [] + + if ( + chunk.imports.length || + Object.entries(chunk.modules).some( + ([id, mod]) => + id !== 'vite/dynamic-import-polyfill' && + mod.renderedLength && + !this.getModuleInfo(id)?.meta.css + ) + ) { // js entry chunk for this page - { + assetTags.push({ tag: 'script', attrs: { type: 'module', crossorigin: true, src: toPublicPath(chunk.fileName, config) } - }, + }) + } else { + // entry js chunk was effectively empty, prevent rollup outputting it + delete bundle[chunk.fileName] + } + + assetTags.push( // preload for imports ...getPreloadLinksForChunk(chunk), ...getCssTagsForChunk(chunk) - ] + ) - result = injectToHead(result, assetTags) + if (assetTags.length) { + result = injectToHead(result, assetTags) + } } // inject css link when cssCodeSplit is false