Skip to content

Commit dad6993

Browse files
authored
refactor!: rewrite with improvements (#30)
1 parent ef7711c commit dad6993

15 files changed

+832
-711
lines changed

README.md

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![Dependencies][david-dm-src]][david-dm-href]
77
<!-- [![Codecov][codecov-src]][codecov-href] -->
88

9-
SSR Bundle Renderer for Vue 3 using [bundle-runner](https://github.com/nuxt-contrib/bundle-runner).
9+
SSR Bundle Renderer for Vue 3.
1010

1111
## Install
1212

@@ -26,21 +26,14 @@ import { createRenderer } from 'vue-bundle-renderer'
2626
declare function createRenderer(createApp:, renderOptions: RenderOptions)
2727
```
2828

29-
### `createBundleRenderer`
29+
### `normalizeClientManifest`
30+
31+
If using a webpack manifest, you should normalize it with this function before passing it to `createRenderer`.
3032

3133
```ts
32-
import { createBundleRenderer } from 'vue-bundle-renderer'
33-
34-
declare function createBundleRenderer(bundle, renderOptions: BundleRenderOptions)
35-
36-
type BundleRenderOptions = {
37-
runInNewContext?: boolean | 'once';
38-
basedir?: string;
39-
renderToString: typeof import('@vue/server-renderer').renderToString;
40-
bundleRunner: typeof import('bundle-runner');
41-
clientManifest?: ClientManifest;
42-
publicPath?: string;
43-
}
34+
import { normalizeClientManifest } from 'vue-bundle-renderer/legacy'
35+
36+
declare function normalizeClientManifest(manifest: ClientManifest | LegacyClientManifest)
4437
```
4538

4639
## Credits

build.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { defineBuildConfig } from 'unbuild'
22

33
export default defineBuildConfig({
44
externals: [
5+
'vite',
56
'@vue/server-renderer'
67
]
78
})

legacy.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './dist/legacy'

package.json

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,41 @@
88
".": {
99
"require": "./dist/index.cjs",
1010
"import": "./dist/index.mjs"
11+
},
12+
"./legacy": {
13+
"require": "./dist/legacy.cjs",
14+
"import": "./dist/legacy.mjs"
1115
}
1216
},
1317
"main": "./dist/index.cjs",
1418
"module": "./dist/index.mjs",
1519
"types": "./dist/index.d.ts",
1620
"files": [
17-
"dist"
21+
"dist",
22+
"legacy.d.ts"
1823
],
1924
"scripts": {
2025
"build": "unbuild",
2126
"lint": "eslint --ext .ts src",
2227
"release": "yarn test && yarn build && standard-version && git push --follow-tags && npm publish",
2328
"test": "yarn lint && yarn test:unit",
24-
"test:unit": "mocha -r jiti/register test/*.test.*"
29+
"test:unit": "vitest"
2530
},
2631
"dependencies": {
27-
"bundle-runner": "^0.0.1"
32+
"ufo": "^0.8.3"
2833
},
2934
"devDependencies": {
3035
"@nuxtjs/eslint-config-typescript": "latest",
3136
"@rollup/plugin-typescript": "latest",
32-
"@types/chai": "latest",
33-
"@types/mocha": "latest",
3437
"@vue/server-renderer": "latest",
35-
"chai": "latest",
3638
"eslint": "latest",
37-
"jiti": "latest",
38-
"mocha": "latest",
3939
"rollup": "latest",
4040
"rollup-plugin-babel": "latest",
4141
"rollup-plugin-node-resolve": "latest",
4242
"standard-version": "latest",
4343
"typescript": "latest",
44-
"unbuild": "latest"
44+
"unbuild": "latest",
45+
"vite": "^3.0.3",
46+
"vitest": "0.19.1"
4547
}
4648
}

src/bundle-renderer.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
export * from './bundle-renderer'
21
export * from './renderer'

src/legacy.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import type { Manifest } from 'vite'
2+
import { isJS, isCSS } from './utils'
3+
4+
// Comment out in dev mode for better type support
5+
// const type = Symbol('type')
6+
// type As<T, L> = T & { [type]: L }
7+
type Identifier = string // & As<string, 'Identifier'>
8+
type OutputPath = string // & As<string, 'OutputPath'>
9+
10+
// Vue2 Webpack client manifest format
11+
export interface LegacyClientManifest {
12+
publicPath: string
13+
all: Array<OutputPath>
14+
initial: Array<OutputPath>
15+
async: Array<OutputPath>
16+
modules: Record<Identifier, Array<number>>
17+
hasNoCssVersion?: { [file: string]: boolean }
18+
}
19+
20+
export function isLegacyClientManifest (clientManifest: Manifest | LegacyClientManifest): clientManifest is LegacyClientManifest {
21+
return 'all' in clientManifest && 'initial' in clientManifest
22+
}
23+
24+
function getIdentifier (output: OutputPath): Identifier
25+
function getIdentifier (output?: undefined): null
26+
function getIdentifier (output?: OutputPath): null | Identifier {
27+
return output ? `_${output}` as Identifier : null
28+
}
29+
30+
export function normalizeClientManifest (manifest: Manifest | LegacyClientManifest = {}): Manifest {
31+
if (!isLegacyClientManifest(manifest)) {
32+
return manifest
33+
}
34+
35+
// Upgrade legacy manifest
36+
// https://github.com/nuxt-contrib/vue-bundle-renderer/issues/12
37+
const clientManifest: Manifest = {}
38+
39+
// Initialize with all keys
40+
for (const outfile of manifest.all) {
41+
if (isJS(outfile)) {
42+
clientManifest[getIdentifier(outfile)] = {
43+
file: outfile
44+
}
45+
}
46+
}
47+
48+
// Prepare first entrypoint to receive extra data
49+
const first = getIdentifier(manifest.initial.find(isJS)!)
50+
if (first) {
51+
if (!(first in clientManifest)) {
52+
throw new Error(
53+
`Invalid manifest - initial entrypoint not in \`all\`: ${manifest.initial.find(isJS)}`
54+
)
55+
}
56+
clientManifest[first].css = []
57+
clientManifest[first].assets = []
58+
clientManifest[first].dynamicImports = []
59+
}
60+
61+
for (const outfile of manifest.initial) {
62+
if (isJS(outfile)) {
63+
clientManifest[getIdentifier(outfile)].isEntry = true
64+
} else if (isCSS(outfile) && first) {
65+
clientManifest[first].css!.push(outfile)
66+
} else if (first) {
67+
clientManifest[first].assets!.push(outfile)
68+
}
69+
}
70+
71+
for (const outfile of manifest.async) {
72+
if (isJS(outfile)) {
73+
const identifier = getIdentifier(outfile)
74+
if (!(identifier in clientManifest)) {
75+
throw new Error(`Invalid manifest - async module not in \`all\`: ${outfile}`)
76+
}
77+
clientManifest[identifier].isDynamicEntry = true
78+
clientManifest[first].dynamicImports!.push(identifier)
79+
} else if (first) {
80+
// Add assets (CSS/JS) as dynamic imports to first entrypoints
81+
// as a workaround so can be prefetched.
82+
const key = isCSS(outfile) ? 'css' : 'assets'
83+
const identifier = getIdentifier(outfile)
84+
clientManifest[identifier] = {
85+
file: '' as OutputPath,
86+
[key]: [outfile]
87+
}
88+
clientManifest[first].dynamicImports!.push(identifier)
89+
}
90+
}
91+
92+
// Map modules to virtual entries
93+
for (const [moduleId, importIndexes] of Object.entries(manifest.modules)) {
94+
const jsFiles = importIndexes.map(index => manifest.all[index]).filter(isJS)
95+
jsFiles.forEach((file) => {
96+
const identifier = getIdentifier(file)
97+
clientManifest[identifier] = {
98+
...clientManifest[identifier],
99+
file
100+
}
101+
})
102+
103+
const mappedIndexes = importIndexes.map(index => manifest.all[index])
104+
clientManifest[moduleId as Identifier] = {
105+
file: '' as OutputPath,
106+
imports: jsFiles.map(id => getIdentifier(id)),
107+
css: mappedIndexes.filter(isCSS),
108+
assets: mappedIndexes.filter(i => !isJS(i) && !isCSS(i))
109+
}
110+
}
111+
112+
return clientManifest
113+
}

0 commit comments

Comments
 (0)