@@ -9,8 +9,16 @@ import type { SchemaOrgOptions } from '@vueuse/schema-org'
99import { schemaOrgAutoImports , schemaOrgComponents } from '@vueuse/schema-org'
1010import type { NuxtModule } from '@nuxt/schema'
1111import { dirname } from 'pathe'
12+ import { createUnplugin } from 'unplugin'
13+ import MagicString from 'magic-string'
1214
1315export interface ModuleOptions extends SchemaOrgOptions {
16+ /**
17+ * Should schema.org only be rendered by the server.
18+ *
19+ * Useful for optimising performance as it may not be needed by search engines. Changes runtime package size to 0kb.
20+ */
21+ disableRuntimeScriptsWhenSSR : boolean
1422 /**
1523 * Whether composables will be automatically imported for you.
1624 * @default true
@@ -27,6 +35,8 @@ export interface ModuleHooks {
2735
2836}
2937
38+ const SchemaOrgPkg = '@vueuse/schema-org'
39+
3040export default defineNuxtModule < ModuleOptions > ( {
3141 meta : {
3242 configKey : 'schemaOrg' ,
@@ -35,6 +45,7 @@ export default defineNuxtModule<ModuleOptions>({
3545 } ,
3646 } ,
3747 defaults : {
48+ disableRuntimeScriptsWhenSSR : false ,
3849 autoImportComposables : true ,
3950 autoImportComponents : true ,
4051 } ,
@@ -44,22 +55,24 @@ export default defineNuxtModule<ModuleOptions>({
4455 const runtimeDir = resolve ( './runtime' )
4556 nuxt . options . build . transpile . push ( runtimeDir )
4657
47- // server & client logic are seperated
48- addPlugin ( resolve ( runtimeDir , 'plugin.client' ) )
58+ const registerClientScripts = ! config . disableRuntimeScriptsWhenSSR || nuxt . options . dev
59+
60+ // allow users to opt-out of client side scripts, if it's not dev
61+ if ( registerClientScripts )
62+ addPlugin ( resolve ( runtimeDir , 'plugin.client' ) )
4963 addPlugin ( resolve ( runtimeDir , 'plugin.server' ) )
5064
5165 // avoid unwanted behavior with different package managers
52- const schemaOrgPath = dirname ( await resolvePath ( '@vueuse/schema-org' ) )
53- nuxt . options . alias [ '@vueuse/schema-org' ] = schemaOrgPath
66+ const schemaOrgPath = dirname ( await resolvePath ( SchemaOrgPkg ) )
67+ nuxt . options . alias [ SchemaOrgPkg ] = schemaOrgPath
68+ nuxt . options . build . transpile . push ( ...[ schemaOrgPath , SchemaOrgPkg ] )
5469
55- nuxt . hook ( 'vite:extend ' , ( { config } : any ) => {
70+ nuxt . hook ( 'vite:extendConfig ' , ( config ) => {
5671 config . optimizeDeps = config . optimizeDeps || { }
5772 config . optimizeDeps . exclude = config . optimizeDeps . exclude || [ ]
58- config . optimizeDeps . exclude . push ( ...[ schemaOrgPath , '@vueuse/schema-org' ] )
73+ config . optimizeDeps . exclude . push ( ...[ schemaOrgPath , SchemaOrgPkg ] )
5974 } )
6075
61- nuxt . options . build . transpile . push ( ...[ schemaOrgPath , '@vueuse/schema-org' ] )
62-
6376 addTemplate ( {
6477 filename : 'schemaOrg.config.mjs' ,
6578 getContents : ( ) => `export default ${ JSON . stringify ( { config } ) } ` ,
@@ -69,7 +82,7 @@ export default defineNuxtModule<ModuleOptions>({
6982 nuxt . hooks . hookOnce ( 'autoImports:sources' , ( autoImports ) => {
7083 autoImports . unshift ( {
7184 from : resolve ( './runtime/composables' ) ,
72- imports : schemaOrgAutoImports [ '@vueuse/schema-org' ] ,
85+ imports : schemaOrgAutoImports [ SchemaOrgPkg ] ,
7386 } )
7487 } )
7588 }
@@ -83,5 +96,56 @@ export default defineNuxtModule<ModuleOptions>({
8396 } )
8497 } )
8598 }
99+
100+ if ( ! registerClientScripts ) {
101+ const mockTemplate = addTemplate ( {
102+ filename : 'schema-org-mock.mjs' ,
103+ getContents ( ) {
104+ return schemaOrgAutoImports [ SchemaOrgPkg ]
105+ . map ( s => `export function ${ s } () {}` )
106+ . join ( '\n' )
107+ } ,
108+ } )
109+ addComponent ( {
110+ name : 'SchemaOrgMock' ,
111+ // use mock components if we don't need real ones
112+ export : 'SchemaOrgMock' ,
113+ filePath : schemaOrgPath ,
114+ } )
115+ nuxt . options . alias [ '#schema-org/mock' ] = mockTemplate . dst !
116+
117+ const mockerPlugin = createUnplugin ( ( ) => {
118+ return {
119+ name : 'nuxt-schema-org:mocker' ,
120+ enforce : 'post' ,
121+ transformInclude ( id ) {
122+ // only include users custom vue files
123+ return id . endsWith ( '.vue' ) && id . includes ( nuxt . options . srcDir )
124+ } ,
125+ transform ( code , id ) {
126+ const s = new MagicString ( code )
127+
128+ // swap our composables with mock composables
129+ s . replace ( resolve ( runtimeDir , 'composables' ) , '#schema-org/mock' )
130+ // replace components with mock components
131+ s . replace ( / _ r e s o l v e C o m p o n e n t \( " S c h e m a O r g ( .* ?) " \) / gm, '_resolveComponent("SchemaOrgMock")' )
132+
133+ if ( s . hasChanged ( ) ) {
134+ return {
135+ code : s . toString ( ) ,
136+ map : s . generateMap ( { includeContent : true , source : id } ) ,
137+ }
138+ }
139+ } ,
140+ }
141+ } )
142+
143+ nuxt . hook ( 'vite:extendConfig' , ( config , { isClient } ) => {
144+ if ( isClient ) {
145+ config . plugins = config . plugins || [ ]
146+ config . plugins . push ( mockerPlugin . vite ( ) )
147+ }
148+ } )
149+ }
86150 } ,
87151} ) as NuxtModule < ModuleOptions >
0 commit comments