mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-18 17:35:57 +00:00
feat(nitro): assets driver (#511)
This commit is contained in:
parent
e363ed5853
commit
820a9d0b57
@ -64,7 +64,7 @@
|
|||||||
"table": "^6.7.1",
|
"table": "^6.7.1",
|
||||||
"ufo": "^0.7.9",
|
"ufo": "^0.7.9",
|
||||||
"unenv": "^0.3.3",
|
"unenv": "^0.3.3",
|
||||||
"unstorage": "^0.2.3",
|
"unstorage": "^0.2.5",
|
||||||
"upath": "^2.0.1",
|
"upath": "^2.0.1",
|
||||||
"vue": "3.2.10",
|
"vue": "3.2.10",
|
||||||
"vue-bundle-renderer": "^0.3.0",
|
"vue-bundle-renderer": "^0.3.0",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { promises as fsp } from 'fs'
|
import { promises as fsp } from 'fs'
|
||||||
|
import type { Plugin } from 'rollup'
|
||||||
import createEtag from 'etag'
|
import createEtag from 'etag'
|
||||||
import mime from 'mime'
|
import mime from 'mime'
|
||||||
import { resolve } from 'upath'
|
import { resolve } from 'upath'
|
||||||
import globby from 'globby'
|
import globby from 'globby'
|
||||||
import type { Plugin } from 'rollup'
|
|
||||||
import virtual from './virtual'
|
import virtual from './virtual'
|
||||||
|
|
||||||
export interface AssetOptions {
|
export interface AssetOptions {
|
||||||
@ -16,60 +16,26 @@ export interface AssetOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Asset {
|
||||||
|
fsPath: string,
|
||||||
|
meta: {
|
||||||
|
type?: string,
|
||||||
|
etag?: string,
|
||||||
|
mtime?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function assets (opts: AssetOptions): Plugin {
|
export function assets (opts: AssetOptions): Plugin {
|
||||||
type Asset = {
|
|
||||||
fsPath: string,
|
|
||||||
meta: {
|
|
||||||
type?: string,
|
|
||||||
etag?: string,
|
|
||||||
mtime?: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const assetUtils = `
|
|
||||||
export function readAsset (id) {
|
|
||||||
return getAsset(id).read()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function statAsset (id) {
|
|
||||||
return getAsset(id).meta
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
if (!opts.inline) {
|
if (!opts.inline) {
|
||||||
return virtual({
|
// Development: Use filesystem
|
||||||
'#assets': `
|
return virtual({ '#assets': getAssetsDev(opts.dirs) })
|
||||||
import { statSync, promises as fsp } from 'fs'
|
|
||||||
import { resolve } from 'path'
|
|
||||||
|
|
||||||
const dirs = ${JSON.stringify(opts.dirs)}
|
|
||||||
|
|
||||||
${assetUtils}
|
|
||||||
|
|
||||||
export function getAsset (id) {
|
|
||||||
for (const dirname in dirs) {
|
|
||||||
if (id.startsWith(dirname + '/')) {
|
|
||||||
const dirOpts = dirs[dirname]
|
|
||||||
const path = resolve(dirOpts.dir, id.substr(dirname.length + 1))
|
|
||||||
let stat = statSync(path)
|
|
||||||
const asset = {
|
|
||||||
read: () => fsp.readFile(path, 'utf-8'),
|
|
||||||
meta: {
|
|
||||||
mtime: stat.mtime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return asset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('Asset dir not found: ' + id)
|
|
||||||
}
|
|
||||||
`
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Production: Bundle assets
|
||||||
return virtual({
|
return virtual({
|
||||||
'#assets': {
|
'#assets': {
|
||||||
async load () {
|
async load () {
|
||||||
|
// Scan all assets
|
||||||
const assets: Record<string, Asset> = {}
|
const assets: Record<string, Asset> = {}
|
||||||
for (const assetdir in opts.dirs) {
|
for (const assetdir in opts.dirs) {
|
||||||
const dirOpts = opts.dirs[assetdir]
|
const dirOpts = opts.dirs[assetdir]
|
||||||
@ -88,17 +54,55 @@ export function getAsset (id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const inlineAssets = `const assets = {\n${Object.keys(assets).map(id =>
|
return getAssetProd(assets)
|
||||||
` ['${id}']: {\n read: () => import('${assets[id].fsPath}').then(r => r.default || r),\n meta: ${JSON.stringify(assets[id].meta)}\n }`
|
|
||||||
).join(',\n')}\n}`
|
|
||||||
return `${inlineAssets}\n${assetUtils}
|
|
||||||
export function getAsset (id) {
|
|
||||||
if (!assets[id]) {
|
|
||||||
throw new Error('Asset not found : ' + id)
|
|
||||||
}
|
|
||||||
return assets[id]
|
|
||||||
}`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAssetsDev (dirs) {
|
||||||
|
return `
|
||||||
|
import { createStorage } from 'unstorage'
|
||||||
|
import fsDriver from 'unstorage/drivers/fs'
|
||||||
|
|
||||||
|
const dirs = ${JSON.stringify(dirs)}
|
||||||
|
|
||||||
|
export const assets = createStorage()
|
||||||
|
|
||||||
|
for (const [dirname, dirOpts] of Object.entries(dirs)) {
|
||||||
|
assets.mount(dirname, fsDriver({ base: dirOpts.dir }))
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeKey (key) {
|
||||||
|
return key.replace(/[/\\\\]/g, ':').replace(/^:|:$/g, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAssetProd (assets: Record<string, Asset>) {
|
||||||
|
return `
|
||||||
|
const _assets = {\n${Object.entries(assets).map(([id, asset]) =>
|
||||||
|
` ['${normalizeKey(id)}']: {\n import: () => import('${asset.fsPath}').then(r => r.default || r),\n meta: ${JSON.stringify(asset.meta)}\n }`
|
||||||
|
).join(',\n')}\n}
|
||||||
|
|
||||||
|
${normalizeKey.toString()}
|
||||||
|
|
||||||
|
export const assets = {
|
||||||
|
getKeys() {
|
||||||
|
return Object.keys(_assets)
|
||||||
|
},
|
||||||
|
hasItem (id) {
|
||||||
|
id = normalizeKey(id)
|
||||||
|
return id in _assets
|
||||||
|
},
|
||||||
|
getItem (id) {
|
||||||
|
id = normalizeKey(id)
|
||||||
|
return _assets[id] ? _assets[id].import() : null
|
||||||
|
},
|
||||||
|
getMeta (id) {
|
||||||
|
id = normalizeKey(id)
|
||||||
|
return _assets[id] ? _assets[id].meta : {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
@ -32,10 +32,14 @@ export function storage (opts: StorageOptions) {
|
|||||||
return virtual({
|
return virtual({
|
||||||
'#storage': `
|
'#storage': `
|
||||||
import { createStorage } from 'unstorage'
|
import { createStorage } from 'unstorage'
|
||||||
|
import { assets } from '#assets'
|
||||||
|
|
||||||
${driverImports.map(i => `import ${getImportName(i)} from '${i}'`).join('\n')}
|
${driverImports.map(i => `import ${getImportName(i)} from '${i}'`).join('\n')}
|
||||||
|
|
||||||
export const storage = createStorage({})
|
export const storage = createStorage({})
|
||||||
|
|
||||||
|
storage.mount('/assets', assets)
|
||||||
|
|
||||||
${mounts.map(m => `storage.mount('${m.path}', ${getImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
|
${mounts.map(m => `storage.mount('${m.path}', ${getImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
10
packages/nitro/types/shims.d.ts
vendored
10
packages/nitro/types/shims.d.ts
vendored
@ -1,7 +1,6 @@
|
|||||||
import type { $Fetch } from 'ohmyfetch'
|
|
||||||
import type { Storage } from 'unstorage'
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
import type { $Fetch } from 'ohmyfetch'
|
||||||
|
|
||||||
// eslint-disable-next-line no-var
|
// eslint-disable-next-line no-var
|
||||||
var $fetch: $Fetch
|
var $fetch: $Fetch
|
||||||
namespace NodeJS {
|
namespace NodeJS {
|
||||||
@ -12,6 +11,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare module '#storage' {
|
declare module '#storage' {
|
||||||
|
import type { Storage } from 'unstorage'
|
||||||
export const storage: Storage
|
export const storage: Storage
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,5 +19,7 @@ declare module '#assets' {
|
|||||||
export interface AssetMeta { type?: string, etag?: string, mtime?: string }
|
export interface AssetMeta { type?: string, etag?: string, mtime?: string }
|
||||||
export function readAsset<T=any>(id: string): Promise<T>
|
export function readAsset<T=any>(id: string): Promise<T>
|
||||||
export function statAsset(id: string): Promise<AssetMeta>
|
export function statAsset(id: string): Promise<AssetMeta>
|
||||||
export function getAsset<T=any>(id: string): { read: () => Promise<T>, meta: AssetMeta }
|
export function getKeys() : Promise<string[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default {}
|
||||||
|
67
yarn.lock
67
yarn.lock
@ -1523,7 +1523,7 @@ __metadata:
|
|||||||
ufo: ^0.7.9
|
ufo: ^0.7.9
|
||||||
unbuild: ^0.4.2
|
unbuild: ^0.4.2
|
||||||
unenv: ^0.3.3
|
unenv: ^0.3.3
|
||||||
unstorage: ^0.2.3
|
unstorage: ^0.2.5
|
||||||
upath: ^2.0.1
|
upath: ^2.0.1
|
||||||
vue: 3.2.10
|
vue: 3.2.10
|
||||||
vue-bundle-renderer: ^0.3.0
|
vue-bundle-renderer: ^0.3.0
|
||||||
@ -4532,7 +4532,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"chokidar@npm:3.5.2, chokidar@npm:^3.5.1, chokidar@npm:^3.5.2":
|
"chokidar@npm:3.5.2, chokidar@npm:^3.5.2":
|
||||||
version: 3.5.2
|
version: 3.5.2
|
||||||
resolution: "chokidar@npm:3.5.2"
|
resolution: "chokidar@npm:3.5.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7732,9 +7732,9 @@ fsevents@~2.3.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ioredis@npm:^4.27.3":
|
"ioredis@npm:^4.27.9":
|
||||||
version: 4.27.7
|
version: 4.27.9
|
||||||
resolution: "ioredis@npm:4.27.7"
|
resolution: "ioredis@npm:4.27.9"
|
||||||
dependencies:
|
dependencies:
|
||||||
cluster-key-slot: ^1.1.0
|
cluster-key-slot: ^1.1.0
|
||||||
debug: ^4.3.1
|
debug: ^4.3.1
|
||||||
@ -7747,7 +7747,7 @@ fsevents@~2.3.2:
|
|||||||
redis-errors: ^1.2.0
|
redis-errors: ^1.2.0
|
||||||
redis-parser: ^3.0.0
|
redis-parser: ^3.0.0
|
||||||
standard-as-callback: ^2.1.0
|
standard-as-callback: ^2.1.0
|
||||||
checksum: 42c2f242b3c91202578415dc39fbc9e9ecff58f19acbd91b654cbe12877181e18dbeb6c12b3e71225a7cc928cc4e34f536953375978093c7c1a6f7417a9dfd84
|
checksum: 0472f20366759fe17c71c42105869dbaba99ad54e3fc14428cd6e1d28f8767ff1aea03bfc0228b29bf6030d7ae1ac856941ab6698c850a9b27fd8a17328e7f9f
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -9990,17 +9990,6 @@ fsevents@~2.3.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ohmyfetch@npm:^0.2.0":
|
|
||||||
version: 0.2.0
|
|
||||||
resolution: "ohmyfetch@npm:0.2.0"
|
|
||||||
dependencies:
|
|
||||||
destr: ^1.1.0
|
|
||||||
node-fetch: ^2.6.1
|
|
||||||
ufo: ^0.6.10
|
|
||||||
checksum: 58afffe238610d2b8829d1f90949cdc776a0d531cd4b9f88f7d0c4ab82550179b810e9b0e0197212216a1722e630149421b4e2b710fa92ed72fa739c28f935cb
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"ohmyfetch@npm:^0.3.1":
|
"ohmyfetch@npm:^0.3.1":
|
||||||
version: 0.3.1
|
version: 0.3.1
|
||||||
resolution: "ohmyfetch@npm:0.3.1"
|
resolution: "ohmyfetch@npm:0.3.1"
|
||||||
@ -13418,14 +13407,7 @@ fsevents@~2.3.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ufo@npm:^0.6.10":
|
"ufo@npm:^0.7.9":
|
||||||
version: 0.6.11
|
|
||||||
resolution: "ufo@npm:0.6.11"
|
|
||||||
checksum: cf73c7f3e62413237cb8b763b2ae39ec9b83a630644a9ceac721c6394c62d562f1d7deb117e7b0c35f5a29a4c88b5e67a8c1ebf0d41543b8acc4c44e5dd607df
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"ufo@npm:^0.7.5, ufo@npm:^0.7.9":
|
|
||||||
version: 0.7.9
|
version: 0.7.9
|
||||||
resolution: "ufo@npm:0.7.9"
|
resolution: "ufo@npm:0.7.9"
|
||||||
checksum: 8a141889382dfe9fe42af625316ea0bc60e287ed81275befa699d3c099af44232720ea7b72d5ea738e4766e79adb8dc901bd7f788f9c2057d0ec2389d9f06df5
|
checksum: 8a141889382dfe9fe42af625316ea0bc60e287ed81275befa699d3c099af44232720ea7b72d5ea738e4766e79adb8dc901bd7f788f9c2057d0ec2389d9f06df5
|
||||||
@ -13603,21 +13585,21 @@ fsevents@~2.3.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"unstorage@npm:^0.2.3":
|
"unstorage@npm:^0.2.5":
|
||||||
version: 0.2.3
|
version: 0.2.5
|
||||||
resolution: "unstorage@npm:0.2.3"
|
resolution: "unstorage@npm:0.2.5"
|
||||||
dependencies:
|
dependencies:
|
||||||
anymatch: ^3.1.1
|
anymatch: ^3.1.1
|
||||||
chokidar: ^3.5.1
|
chokidar: ^3.5.2
|
||||||
destr: ^1.1.0
|
destr: ^1.1.0
|
||||||
h3: ^0.2.10
|
h3: ^0.2.10
|
||||||
ioredis: ^4.27.3
|
ioredis: ^4.27.9
|
||||||
listhen: ^0.2.4
|
listhen: ^0.2.4
|
||||||
mri: ^1.1.6
|
mri: ^1.1.6
|
||||||
ohmyfetch: ^0.2.0
|
ohmyfetch: ^0.3.1
|
||||||
ufo: ^0.7.5
|
ufo: ^0.7.9
|
||||||
ws: ^7.4.5
|
ws: ^8.2.1
|
||||||
checksum: 88996f454624a8da10c140f28441376ceee84047bff7aad7c9df7b8bfd8f4768042ce97c63713bad1c5d42c66c1fad367c7e9727b7241260ec75e04350f5b785
|
checksum: 214042a12eaf4ac9b17ee35058681330f57c7d9570f0e30cb46fd96b9d0952ff73296e6bf43c40162d7f4f86df29b249d2d1df7db0d7c1d9d98b72c2a0b50ed8
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -14327,7 +14309,7 @@ fsevents@~2.3.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ws@npm:^7.3.1, ws@npm:^7.4.5, ws@npm:^7.4.6":
|
"ws@npm:^7.3.1, ws@npm:^7.4.6":
|
||||||
version: 7.5.3
|
version: 7.5.3
|
||||||
resolution: "ws@npm:7.5.3"
|
resolution: "ws@npm:7.5.3"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -14342,6 +14324,21 @@ fsevents@~2.3.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"ws@npm:^8.2.1":
|
||||||
|
version: 8.2.1
|
||||||
|
resolution: "ws@npm:8.2.1"
|
||||||
|
peerDependencies:
|
||||||
|
bufferutil: ^4.0.1
|
||||||
|
utf-8-validate: ^5.0.2
|
||||||
|
peerDependenciesMeta:
|
||||||
|
bufferutil:
|
||||||
|
optional: true
|
||||||
|
utf-8-validate:
|
||||||
|
optional: true
|
||||||
|
checksum: 22906903c7952790a911627f99e3419d8f251a6a540d9ba4f334a7e0865d7ea7026d8ad23829c3c0f2843a9f15bdb91c646e7f8853a5a5ba25a57dea2cf7d416
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"xml-name-validator@npm:^3.0.0":
|
"xml-name-validator@npm:^3.0.0":
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
resolution: "xml-name-validator@npm:3.0.0"
|
resolution: "xml-name-validator@npm:3.0.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user