Create local Nuxt modules inside a Nuxt project: Do I need a build step?

Hey there! Question to all that worked with modules, especially local ones: I want to create some modules that will live only locally inside my nuxt project. I have done that by creating a modules/my-module/module.ts and modules/my-module/runtime/plugin.ts like you would get from the module starter template. I am using the module in my main app like:
export default defineNuxtConfig({
modules: ['./modules/my-module/module.ts']
})
export default defineNuxtConfig({
modules: ['./modules/my-module/module.ts']
})
This works so far. My question: Now I want to install some dependencies and also inject some types from this module into my main app. Normally you would have "prepack": "nuxt-module-build", in your package.json which would generate some dist/...mjs files. Is this needed when my module is locally installed directly inside a nuxt app? Or can I get types and dependencies to work without that.
4 Replies
conner
conner2y ago
@Fabian B. If you have the types directly in the project you just can export it, or am I understanding you wrong?
Fabian B.
Fabian B.OP2y ago
@conner Yeah technically, but this would mean I have to manually import it in my main app too. I want it to function like a real module, so when doing stuff like: Inside main app:
// `myService` is untyped, but I want it to be typed
import { myService } from '#my-module/server'
// `myService` is untyped, but I want it to be typed
import { myService } from '#my-module/server'
Inside module.ts:
nuxt.hook("nitro:config", (nitroConfig) => {
nitroConfig.alias = nitroConfig.alias || {};

// Inline module runtime in Nitro bundle
nitroConfig.externals = defu(
typeof nitroConfig.externals === "object" ? nitroConfig.externals : {},
{
inline: [resolver.resolve("./runtime")],
}
);
nitroConfig.alias["#my-module/server"] = resolveRuntimeModule("./services");
});

addTemplate({
filename: "types/my-module.d.ts",
getContents: () =>
[
"declare module '#my-module/server' {",
` const myService: typeof import('${resolver.resolve(
"./runtime/services"
)}').myService`,
"}",
].join("\n"),
});

nuxt.hook("prepare:types", (options) => {
options.references.push({
path: resolver.resolve(nuxt.options.buildDir, "types/supabase.d.ts"),
});
});
nuxt.hook("nitro:config", (nitroConfig) => {
nitroConfig.alias = nitroConfig.alias || {};

// Inline module runtime in Nitro bundle
nitroConfig.externals = defu(
typeof nitroConfig.externals === "object" ? nitroConfig.externals : {},
{
inline: [resolver.resolve("./runtime")],
}
);
nitroConfig.alias["#my-module/server"] = resolveRuntimeModule("./services");
});

addTemplate({
filename: "types/my-module.d.ts",
getContents: () =>
[
"declare module '#my-module/server' {",
` const myService: typeof import('${resolver.resolve(
"./runtime/services"
)}').myService`,
"}",
].join("\n"),
});

nuxt.hook("prepare:types", (options) => {
options.references.push({
path: resolver.resolve(nuxt.options.buildDir, "types/supabase.d.ts"),
});
});
This does currently work, meaning I can use myService, but it's untyped. For typing, I probably would have to build that dist. The interesting thing is, even the addTemplate works without build. So it adds the typings file into my main app as soon as I start the devserver of the main app. So I'm not sure why it's untyped
conner
conner2y ago
I think you need the build step.
Fabian B.
Fabian B.OP2y ago
@conner Yeah I think there is no way around it if I want to use all modules features. Thanks anyway!
Want results from more Discord servers?
Add your server