From b7754de8c36b10aba69cd0307c9aa01ca996e122 Mon Sep 17 00:00:00 2001 From: Sacha STAFYNIAK Date: Sat, 1 Oct 2022 20:29:24 +0200 Subject: [PATCH 1/6] feat: add dev-only component --- packages/nuxt/src/app/components/dev-only.mjs | 11 +++++++++++ packages/nuxt/src/core/nuxt.ts | 6 ++++++ 2 files changed, 17 insertions(+) create mode 100644 packages/nuxt/src/app/components/dev-only.mjs diff --git a/packages/nuxt/src/app/components/dev-only.mjs b/packages/nuxt/src/app/components/dev-only.mjs new file mode 100644 index 00000000000..c9f59c40494 --- /dev/null +++ b/packages/nuxt/src/app/components/dev-only.mjs @@ -0,0 +1,11 @@ +import { defineComponent } from 'vue' + +export default defineComponent({ + name: 'DevOnly', + setup (_, { slots }) { + if (process.dev) { + return () => slots.default?.() + } + return () => null + } +}) diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index 81305b82691..d8f8e9b0289 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -139,6 +139,12 @@ async function initNuxt (nuxt: Nuxt) { filePath: resolve(nuxt.options.appDir, 'components/client-only') }) + // Add + addComponent({ + name: 'DevOnly', + filePath: resolve(nuxt.options.appDir, 'components/dev-only') + }) + // Add addComponent({ name: 'ServerPlaceholder', From 6cec7af4cc61c63e363e0d804ee62e2027305545 Mon Sep 17 00:00:00 2001 From: Sacha STAFYNIAK Date: Sat, 1 Oct 2022 20:38:57 +0200 Subject: [PATCH 2/6] chore(docs): add dev-only component documentation --- .../2.directory-structure/1.components.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/content/2.guide/2.directory-structure/1.components.md b/docs/content/2.guide/2.directory-structure/1.components.md index 2466d2f9629..7bc3296ceda 100644 --- a/docs/content/2.guide/2.directory-structure/1.components.md +++ b/docs/content/2.guide/2.directory-structure/1.components.md @@ -222,6 +222,22 @@ This feature only works with Nuxt auto-imports. Explicitly importing these compo ``` +## `` Component + +Nuxt also provides a `` component to render a component only during development. The content will not be included in production builds. + +```html{}[pages/example.vue] + +``` + ## Library Authors Making Vue component libraries with automatic tree-shaking and component registration is super easy ✨ From 885d2af28aed900c2e57318eb4cbb3d5384b4965 Mon Sep 17 00:00:00 2001 From: Sacha STAFYNIAK Date: Sat, 1 Oct 2022 20:41:23 +0200 Subject: [PATCH 3/6] chore(docs): use lazy component in dev-only example --- docs/content/2.guide/2.directory-structure/1.components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/2.guide/2.directory-structure/1.components.md b/docs/content/2.guide/2.directory-structure/1.components.md index 7bc3296ceda..7ba87e8e017 100644 --- a/docs/content/2.guide/2.directory-structure/1.components.md +++ b/docs/content/2.guide/2.directory-structure/1.components.md @@ -232,7 +232,7 @@ Nuxt also provides a `` component to render a component only during dev - + From fd6b0bd392918602413df6425b9acccfe3dddb7e Mon Sep 17 00:00:00 2001 From: Sacha STAFYNIAK Date: Thu, 6 Oct 2022 01:23:23 +0200 Subject: [PATCH 4/6] feat(dev-only): use unplugin to tree-share on build --- packages/nuxt/src/app/components/dev-only.mjs | 5 +-- packages/nuxt/src/core/nuxt.ts | 5 +++ packages/nuxt/src/core/plugins/dev-only.ts | 45 +++++++++++++++++++ playground/app.vue | 2 + 4 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 packages/nuxt/src/core/plugins/dev-only.ts diff --git a/packages/nuxt/src/app/components/dev-only.mjs b/packages/nuxt/src/app/components/dev-only.mjs index c9f59c40494..2c04d2f1915 100644 --- a/packages/nuxt/src/app/components/dev-only.mjs +++ b/packages/nuxt/src/app/components/dev-only.mjs @@ -3,9 +3,6 @@ import { defineComponent } from 'vue' export default defineComponent({ name: 'DevOnly', setup (_, { slots }) { - if (process.dev) { - return () => slots.default?.() - } - return () => null + return () => slots.default?.() } }) diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index d8f8e9b0289..5fd9443cd52 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -17,6 +17,7 @@ import { version } from '../../package.json' import { ImportProtectionPlugin, vueAppPatterns } from './plugins/import-protection' import { UnctxTransformPlugin } from './plugins/unctx' import { TreeShakePlugin } from './plugins/tree-shake' +import { DevOnlyPlugin } from './plugins/dev-only' import { addModuleTranspiles } from './modules' 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 }) addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap.server, treeShake: removeFromServer }), { client: 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 diff --git a/packages/nuxt/src/core/plugins/dev-only.ts b/packages/nuxt/src/core/plugins/dev-only.ts new file mode 100644 index 00000000000..84d88e8f69c --- /dev/null +++ b/packages/nuxt/src/core/plugins/dev-only.ts @@ -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 = /(:?[\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 + } + } + } + } +}) diff --git a/playground/app.vue b/playground/app.vue index c93a9dcaf5f..1a1ec7720b3 100644 --- a/playground/app.vue +++ b/playground/app.vue @@ -5,6 +5,8 @@
Nuxt 3 Playground + + Development mode
From 1f6fb14c40a2293fc730932e4b7ba4b4d187225e Mon Sep 17 00:00:00 2001 From: Sacha STAFYNIAK Date: Thu, 6 Oct 2022 12:51:53 +0200 Subject: [PATCH 5/6] fix(dev-only): ensure content is not shown on build --- packages/nuxt/src/app/components/dev-only.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/nuxt/src/app/components/dev-only.mjs b/packages/nuxt/src/app/components/dev-only.mjs index 2c04d2f1915..c9f59c40494 100644 --- a/packages/nuxt/src/app/components/dev-only.mjs +++ b/packages/nuxt/src/app/components/dev-only.mjs @@ -3,6 +3,9 @@ import { defineComponent } from 'vue' export default defineComponent({ name: 'DevOnly', setup (_, { slots }) { - return () => slots.default?.() + if (process.dev) { + return () => slots.default?.() + } + return () => null } }) From e92889b026a6e0f897e146e0d64441ec8fd26f25 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 26 Oct 2022 14:35:15 +0200 Subject: [PATCH 6/6] small changes --- docs/content/2.guide/2.directory-structure/1.components.md | 4 +++- packages/nuxt/src/app/components/dev-only.mjs | 4 ++-- playground/app.vue | 2 -- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/content/2.guide/2.directory-structure/1.components.md b/docs/content/2.guide/2.directory-structure/1.components.md index 69f348f44bd..9e959c11ce7 100644 --- a/docs/content/2.guide/2.directory-structure/1.components.md +++ b/docs/content/2.guide/2.directory-structure/1.components.md @@ -225,7 +225,9 @@ This feature only works with Nuxt auto-imports and `#components` imports. Explic ## `` Component -Nuxt also provides a `` component to render a component only during development. The content will not be included in production builds. +Nuxt provides the `` component to render a component only during development. + +The content will not be included in production builds and tree-shaken. ```html{}[pages/example.vue]