feat: use entry instead of manualChunk

This commit is contained in:
julien huang 2023-08-28 23:25:47 +02:00
parent a6d2dddd01
commit b3fd481393

View File

@ -1,5 +1,5 @@
import { pathToFileURL } from 'node:url' import { pathToFileURL } from 'node:url'
import { basename, join } from 'node:path' import { join } from 'node:path'
import fs from 'node:fs' import fs from 'node:fs'
import type { Component } from '@nuxt/schema' import type { Component } from '@nuxt/schema'
import { parseURL } from 'ufo' import { parseURL } from 'ufo'
@ -7,6 +7,8 @@ import { createUnplugin } from 'unplugin'
import MagicString from 'magic-string' import MagicString from 'magic-string'
import { ELEMENT_NODE, parse, walk } from 'ultrahtml' import { ELEMENT_NODE, parse, walk } from 'ultrahtml'
import { hash } from 'ohash' import { hash } from 'ohash'
import { resolvePath } from '@nuxt/kit'
import { basename } from 'pathe'
import { isVue } from '../core/utils' import { isVue } from '../core/utils'
interface ServerOnlyComponentTransformPluginOptions { interface ServerOnlyComponentTransformPluginOptions {
@ -145,52 +147,96 @@ export const componentsChunkPlugin = createUnplugin((options: ComponentChunkOpti
return { return {
name: 'componentsChunkPlugin', name: 'componentsChunkPlugin',
vite: { vite: {
config (config) { async config (config) {
const components = options.getComponents() const components = options.getComponents()
config.build = config.build || {} config.build = config.build || {}
config.build.rollupOptions = config.build.rollupOptions || {} config.build.rollupOptions = config.build.rollupOptions || {}
config.build.rollupOptions.output = config.build.rollupOptions.output || {} config.build.rollupOptions.output = config.build.rollupOptions.output || {}
const componentManualChunk = (id: string) => { config.build.rollupOptions.input = config.build.rollupOptions.input || {}
if (components.some(c => c.mode !== 'server' && !c.island && c.filePath === parseURL(decodeURIComponent(pathToFileURL(id).href)).pathname)) { config.build.lib = {
return basename(id) entry: {},
formats: ['es'],
fileName: '[name].mjs',
name: 'components'
}
for (const component of components) {
if (component.mode === 'client' || component.mode === 'all') {
// (config.build.lib.entry as Record<string, string>)[component.pascalName] = await resolvePath(component.filePath)
(config.build.rollupOptions.input as Record<string, string>)[component.pascalName] = await resolvePath(component.filePath)
} }
} }
if (Array.isArray(config.build.rollupOptions.output)) {
config.build.rollupOptions.output.forEach((output) => { // const componentManualChunk = (id: string) => {
output.manualChunks = componentManualChunk // if (components.some(c => c.mode !== 'server' && !c.island && c.filePath === parseURL(decodeURIComponent(pathToFileURL(id).href)).pathname)) {
}) // return basename(id)
} else { // }
config.build.rollupOptions.output.manualChunks = componentManualChunk // }
} // if (Array.isArray(config.build.rollupOptions.output)) {
// config.build.rollupOptions.output.forEach((output) => {
// output.manualChunks = componentManualChunk
// })
// } else {
// config.build.rollupOptions.output.manualChunks = componentManualChunk
// }
}, },
generateBundle (_opts, bundle) { async generateBundle (_opts, bundle) {
const components = options.getComponents() const components = options.getComponents().filter(c => c.mode === 'client' || c.mode === 'all')
const componentsChunks = Object.entries(bundle).filter(([_chunkPath, chunkInfo]) => { const pathAssociation: Record<string, string> = {}
if (chunkInfo.type !== 'chunk') { return false } for (const [chunkPath, chunkInfo] of Object.entries(bundle)) {
return components.some((component) => { if (chunkInfo.type !== 'chunk') { continue }
for (const component of components) {
if (chunkInfo.facadeModuleId) { if (chunkInfo.facadeModuleId) {
const { pathname } = parseURL(decodeURIComponent(pathToFileURL(chunkInfo.facadeModuleId).href)) const { pathname } = parseURL(decodeURIComponent(pathToFileURL(chunkInfo.facadeModuleId).href))
const isPath = component.filePath === pathname const isPath = await resolvePath(component.filePath) === pathname
if (isPath) { return true } if (isPath) {
chunkInfo.isEntry = false
pathAssociation[component.pascalName] = chunkPath
}
} }
return chunkInfo.moduleIds.map((path) => { // const isWithinChunk = chunkInfo.moduleIds.map((path) => {
return parseURL(decodeURIComponent(pathToFileURL(path).href)).pathname // return parseURL(decodeURIComponent(pathToFileURL(path).href)).pathname
}).includes(component.filePath) // }).includes(component.filePath)
})
})
fs.writeFileSync(join(buildDir, 'components-chunk.mjs'), `export const paths = ${JSON.stringify(componentsChunks.reduce((acc, [chunkPath, chunkInfo]) => { // if (isWithinChunk) {
if (chunkInfo.type === 'chunk' && chunkInfo.name && chunkInfo.exports.length > 0) { return Object.assign(acc, { [withoutClientSuffixAndExtension(chunkInfo.name)]: chunkPath }) } // pathAssociation[component.pascalName] = chunkPath
return acc // }
}, {}))}`) }
}
// const componentsChunks = Object.entries(bundle).reduce((acc, [_chunkPath, chunkInfo]) => {
// if (chunkInfo.type !== 'chunk') { return acc }
// for (const component of components) {
// if (chunkInfo.facadeModuleId) {
// const { pathname } = parseURL(decodeURIComponent(pathToFileURL(chunkInfo.facadeModuleId).href))
// const isPath = component.filePath === pathname
// if (isPath) { return true }
// }
// chunkInfo.moduleIds.map((path) => {
// return parseURL(decodeURIComponent(pathToFileURL(path).href)).pathname
// }).includes(component.filePath)
// }
// return acc
// }, {})
// fs.writeFileSync(join(buildDir, 'components-chunk.mjs'), `export const paths = ${JSON.stringify(componentsChunks.reduce((acc, [chunkPath, chunkInfo]) => {
// if (chunkInfo.type === 'chunk' && chunkInfo.name && chunkInfo.exports.length > 0) {
// return Object.assign(acc, { [withoutClientSuffixAndExtension(chunkInfo.name)]: chunkPath })
// }
// return acc
// }, {}))}`)
fs.writeFileSync(join(buildDir, 'components-chunk.mjs'), `export const paths = ${JSON.stringify(pathAssociation, null, 2)}`)
} }
} }
} }
}) })
function withoutClientSuffixAndExtension (filePath: string): string { // function withoutClientSuffixAndExtension (filePath: string): string {
return filePath.replace(/(\.client)?\.(vue|ts|js)$/, '') // return filePath.replace(/(\.client)?\.(vue|ts|js)$/, '')
} // }