mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
feat: add dev-only component (#7950)
This commit is contained in:
parent
8e1bcae8c6
commit
b010e3e861
@ -223,6 +223,24 @@ This feature only works with Nuxt auto-imports and `#components` imports. Explic
|
|||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `<DevOnly>` Component
|
||||||
|
|
||||||
|
Nuxt provides the `<DevOnly>` component to render a component only during development.
|
||||||
|
|
||||||
|
The content will not be included in production builds and tree-shaken.
|
||||||
|
|
||||||
|
```html{}[pages/example.vue]
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Sidebar />
|
||||||
|
<DevOnly>
|
||||||
|
<!-- this component will only be rendered during development -->
|
||||||
|
<LazyDebugBar />
|
||||||
|
</DevOnly>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## Library Authors
|
## Library Authors
|
||||||
|
|
||||||
Making Vue component libraries with automatic tree-shaking and component registration is super easy ✨
|
Making Vue component libraries with automatic tree-shaking and component registration is super easy ✨
|
||||||
|
11
packages/nuxt/src/app/components/dev-only.mjs
Normal file
11
packages/nuxt/src/app/components/dev-only.mjs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'DevOnly',
|
||||||
|
setup (_, props) {
|
||||||
|
if (process.dev) {
|
||||||
|
return () => props.slots.default?.()
|
||||||
|
}
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
})
|
@ -17,6 +17,7 @@ import { version } from '../../package.json'
|
|||||||
import { ImportProtectionPlugin, vueAppPatterns } from './plugins/import-protection'
|
import { ImportProtectionPlugin, vueAppPatterns } from './plugins/import-protection'
|
||||||
import { UnctxTransformPlugin } from './plugins/unctx'
|
import { UnctxTransformPlugin } from './plugins/unctx'
|
||||||
import { TreeShakePlugin } from './plugins/tree-shake'
|
import { TreeShakePlugin } from './plugins/tree-shake'
|
||||||
|
import { DevOnlyPlugin } from './plugins/dev-only'
|
||||||
import { addModuleTranspiles } from './modules'
|
import { addModuleTranspiles } from './modules'
|
||||||
import { initNitro } from './nitro'
|
import { initNitro } from './nitro'
|
||||||
|
|
||||||
@ -89,6 +90,10 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
addVitePlugin(TreeShakePlugin.vite({ sourcemap: nuxt.options.sourcemap.client, treeShake: removeFromClient }), { server: false })
|
addVitePlugin(TreeShakePlugin.vite({ sourcemap: nuxt.options.sourcemap.client, treeShake: removeFromClient }), { server: false })
|
||||||
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap.server, treeShake: removeFromServer }), { client: false })
|
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap.server, treeShake: removeFromServer }), { client: false })
|
||||||
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap.client, treeShake: removeFromClient }), { server: false })
|
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap.client, treeShake: removeFromClient }), { server: false })
|
||||||
|
|
||||||
|
// DevOnly component tree-shaking - build time only
|
||||||
|
addVitePlugin(DevOnlyPlugin.vite({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))
|
||||||
|
addWebpackPlugin(DevOnlyPlugin.webpack({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: [Experimental] Avoid emitting assets when flag is enabled
|
// TODO: [Experimental] Avoid emitting assets when flag is enabled
|
||||||
@ -139,6 +144,12 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
filePath: resolve(nuxt.options.appDir, 'components/client-only')
|
filePath: resolve(nuxt.options.appDir, 'components/client-only')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Add <DevOnly>
|
||||||
|
addComponent({
|
||||||
|
name: 'DevOnly',
|
||||||
|
filePath: resolve(nuxt.options.appDir, 'components/dev-only')
|
||||||
|
})
|
||||||
|
|
||||||
// Add <ServerPlaceholder>
|
// Add <ServerPlaceholder>
|
||||||
addComponent({
|
addComponent({
|
||||||
name: 'ServerPlaceholder',
|
name: 'ServerPlaceholder',
|
||||||
|
45
packages/nuxt/src/core/plugins/dev-only.ts
Normal file
45
packages/nuxt/src/core/plugins/dev-only.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { pathToFileURL } from 'node:url'
|
||||||
|
import { stripLiteral } from 'strip-literal'
|
||||||
|
import { parseQuery, parseURL } from 'ufo'
|
||||||
|
import MagicString from 'magic-string'
|
||||||
|
import { createUnplugin } from 'unplugin'
|
||||||
|
|
||||||
|
interface DevOnlyPluginOptions {
|
||||||
|
sourcemap?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DevOnlyPlugin = createUnplugin((options: DevOnlyPluginOptions) => {
|
||||||
|
const DEVONLY_COMP_RE = /<dev-?only>(:?[\s\S]*)<\/dev-?only>/gmi
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'nuxt:server-devonly:transfrom',
|
||||||
|
enforce: 'pre',
|
||||||
|
transformInclude (id) {
|
||||||
|
const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href))
|
||||||
|
const { type } = parseQuery(search)
|
||||||
|
|
||||||
|
// vue files
|
||||||
|
if (pathname.endsWith('.vue') && (type === 'template' || !search)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transform (code, id) {
|
||||||
|
if (!code.match(DEVONLY_COMP_RE)) { return }
|
||||||
|
|
||||||
|
const s = new MagicString(code)
|
||||||
|
const strippedCode = stripLiteral(code)
|
||||||
|
for (const match of strippedCode.matchAll(DEVONLY_COMP_RE) || []) {
|
||||||
|
s.remove(match.index!, match.index! + match[0].length)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.hasChanged()) {
|
||||||
|
return {
|
||||||
|
code: s.toString(),
|
||||||
|
map: options.sourcemap
|
||||||
|
? s.generateMap({ source: id, includeContent: true })
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user