N
Nuxt3mo ago
_frdrk_

Modules and instance-configuration-options

I am developing a Nuxt 3 Module to be distributed on NPM as a library. It would act as a module to implement cookie-based authentication, but in order to support stateful-sessions, we need the ability for our users to bring in their own session-storage. In essence, this comes down to implementing an interface we provide and our underlying SDK can work with that. Now I am trying to figure out how to get this instance into the Module from user-land, what I find is the following and I want to sanity check if this is the expected way: - User provides a path to the file that implements the interface and exports the instance - The module uses that path resolve it to an absolute path, and configure an alias (e.g. #my-session-store) to the absolute path - The server-side plugin that is part of the module then uses this alias to dynamically import the file, get the instance from it and pass it down to the instance we create to be used further down the chain. Is this accurate, or are there other / better ways to achieve this?
18 Replies
kapa.ai
kapa.ai3mo ago
Hi @frdrk. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Your proposed approach—having the user provide a path to their implementation, resolving it to an absolute path, setting up an alias (like #my-session-store), and then dynamically importing it in your server-side plugin—is a valid and idiomatic way to allow user-land extensibility in a Nuxt 3 module. The Nuxt module system is designed to be highly flexible, and resolving user-provided paths and setting up aliases is a common pattern. The official documentation describes how to use utilities like createResolver and resolvePath to handle user-supplied paths, and how to inject assets, plugins, or composables into the Nuxt app. While the docs do not provide an exact example for your session-store use case, your outlined method aligns with best practices for module extensibility and dynamic imports in Nuxt 3 modules. Specifically: - You can accept a user option (e.g., sessionStorePath) in your module. - Use createResolver and resolvePath to resolve the user’s file path. - Use Nuxt’s alias system (nuxt.options.alias) to create a custom alias pointing to the resolved path. - In your server-side plugin, import the alias to access the user’s implementation. This pattern is supported by the flexibility described in the module authoring guides, which show how to alter configuration, resolve paths, and inject runtime logic or assets into the Nuxt app. The docs also encourage exposing configuration and runtime options in a way that is type-safe and developer-friendly, which your approach supports by enforcing an interface contract for the user’s implementation Module Anatomy Altering Nuxt Configuration Resolving. If you want to ensure the best developer experience, consider validating the user’s path and providing clear error messages if the file does not exist or does not export the expected instance. Also, document the required interface and usage in your module’s README, as recommended in the best practices Best Practices. In summary: your approach is accurate and aligns with Nuxt 3 module best practices. There are no alternative patterns in the official documentation that would be more suitable for this use case. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@227872143281487872> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
_frdrk_
_frdrk_OP3mo ago
This bot is wonderful 👏 @kapa.ai One last thing, even though I understand how this should work theoretically, I am getting "package import specifier '#my-session-store' is not defined in package ...", but when I console.log nuxt.options.nitro.alias, I can see it be set to:
{
'#my-session-store': 'absolute/path/to/file/in/userland/here.ts'
}
{
'#my-session-store': 'absolute/path/to/file/in/userland/here.ts'
}
Are their ways to troubleshoot this, or is this a known thing that can cause issues and I may be doing something wrong?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The error you're seeing—"package import specifier '#my-session-store' is not defined in package ..."—suggests that while you've set the alias in nuxt.options.nitro.alias, it may not be available in the context where you're trying to import it. This is a known area where issues can arise in Nuxt 3, especially regarding alias resolution between the Nuxt app and Nitro server contexts. From the knowledge sources: - Aliases like ~ and @ are resolved differently in Nuxt and Nitro. For example, within Nuxt, ~ points to app/, but within Nitro, it points to server/. If you want a shared directory between Nuxt and Nitro, it should be a sibling directory, and you should import from a hash alias like #shared Nuxt/Nitro alias context. - You cannot import from your Nuxt directory in your Nitro code. Aliases must be set up correctly and be available in the context where they're used. - If you see errors about aliases not being defined, it may be because the alias is not properly registered in the context (Nuxt vs. Nitro) where the import is happening, or because the file does not exist at the resolved path. Troubleshooting steps: 1. Check the context: Make sure the alias is registered in the correct context (Nuxt or Nitro) for where you're importing it. 2. File existence: Double-check that the file exists at the absolute path you set in the alias. 3. Import timing: Ensure the alias is set before any code tries to import it. 4. Shared directory: If you want to share code between Nuxt and Nitro, place it in a sibling directory and use a hash alias (e.g., #shared), as described in the comments of the linked issue. 5. No Nuxt app aliases in server runtime: Do not use Nuxt app aliases (like #build) in server runtime code, as this will cause errors Stack Overflow: Vue app aliases not allowed in server runtime. If you follow these guidelines and still encounter issues, it may be a limitation or bug in how aliases are handled between Nuxt and Nitro. In that case, reviewing the structure of your project and ensuring that shared code is outside of the Nuxt app directory and properly aliased is recommended. In summary, alias resolution between Nuxt and Nitro can be tricky, and the error you're seeing is a known pitfall if the alias is not set up or used in the correct context Nuxt/Nitro alias context. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@227872143281487872> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
_frdrk_
_frdrk_OP3mo ago
Havent gotten anywhere yet, if anyone would have any ideas, I am all ears ...
_frdrk_
_frdrk_OP3mo ago
@kapa.ai I am still facing the above issue, I have reproduced the behavior I am seeing in a minimal reproduction, any chance that helps you spot the issue? https://github.com/frederikprijck/my-module-nuxt-alias-issue
GitHub
GitHub - frederikprijck/my-module-nuxt-alias-issue
Contribute to frederikprijck/my-module-nuxt-alias-issue development by creating an account on GitHub.
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Thank you for providing a minimal reproduction. Based on the knowledge sources, there are a few known pitfalls and limitations with alias resolution between Nuxt and Nitro, especially when trying to use custom aliases for userland files in server-side code. From the sources: - Alias Contexts Differ: Within Nuxt, ~ points to app/, but within Nitro, it points to server/. For shared code, it should be in a sibling directory and imported via a hash alias (e.g., #shared). Importing from the Nuxt directory in Nitro code is not supported and will cause issues Nuxt/Nitro alias context. - Alias Registration Timing: The alias must be registered before any code attempts to import it. If the alias is set too late, or not in the correct context, it will not be recognized. - No Nuxt App Aliases in Server Runtime: Importing Nuxt app aliases (like #build) in server runtime code is not allowed and will result in errors Stack Overflow: Vue app aliases not allowed in server runtime. Given these points, if your reproduction sets the alias in nuxt.options.nitro.alias but you still get "package import specifier ... is not defined," it is likely due to one of the following: - The alias is not being registered early enough or in the correct context for Nitro to recognize it. - The file you are aliasing is not in a location that Nitro can access (e.g., inside the Nuxt app directory instead of a shared or server directory). - There may be a limitation or bug in how custom aliases are handled for userland files in Nitro. What you can do: - Double-check that the file you are aliasing is outside the Nuxt app directory and accessible to Nitro. - Ensure the alias is registered before any imports occur. - Follow the pattern described in the Nuxt/Nitro alias context issue: use a sibling directory and a hash alias for shared code. If you have already followed these steps and the issue persists in your reproduction, it may be a limitation or bug not fully addressed in the current knowledge sources. In that case, sharing your reproduction with the Nuxt team (as you have done) is the best next step, as they may need to address it in the framework itself. I'm sorry, but the knowledge sources do not provide a more specific solution for your exact scenario beyond these general troubleshooting steps and known limitations. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@227872143281487872> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
_frdrk_
_frdrk_OP3mo ago
Hey @kapa.ai , - The alias is registered before it is being access according to the console.logs I added in both the module and the server-side plugin. - I am not sure I need a sibling directory, as the code is not shared with client and server. But I will give it a try.
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You're correct that a sibling directory is only necessary if you want to share code between the Nuxt app and Nitro server. If your code is strictly server-side, placing it within the server/ directory or another server-only location should be fine. However, the knowledge sources highlight that alias resolution between Nuxt and Nitro can be tricky, and issues often arise if the alias is not registered in the correct context or if the file is not accessible to Nitro at build/runtime. Even if your console logs show the alias is set before access, Nitro and Vite may still not recognize it if it's not properly registered in their respective contexts or if the file path is not resolvable from Nitro's perspective Nuxt/Nitro alias context. Unfortunately, the knowledge sources do not provide a definitive solution for your scenario beyond these general guidelines. If moving the file to a sibling directory and using a hash alias does not resolve the issue, it may be a limitation or bug in Nuxt/Nitro's alias handling. In that case, sharing your reproduction (as you have) is the best way forward, as the maintainers may need to address this in the framework itself. I'm sorry, but there's no more specific troubleshooting advice in the knowledge sources for your exact situation. If you discover a workaround or receive feedback from the Nuxt team, that may provide further clarity. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@227872143281487872> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
_frdrk_
_frdrk_OP3mo ago
@kapa.ai putting the file in #shared works, it also no longer requires me to create a dynamic alias in the module. Unsure if this is what I need tho, as the code realy should be server-side only.
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Placing the file in the shared/ directory and using the #shared alias works because Nuxt is designed to support sharing code between the app and the server through this directory, and it sets up the alias automatically for you. This avoids the need for custom alias configuration in your module. However, as you noted, the shared/ directory is intended for code that is safe to use in both client and server contexts, and it cannot import Vue or Nitro-specific code shared directory docs. If your code is truly server-only and should not be accessible from the client, the ideal place would be within the server/ directory. However, the knowledge sources indicate that aliasing and importing custom userland files in Nitro/server context can be tricky and is a known source of issues, especially if you try to set up dynamic aliases for files outside the expected structure Nuxt/Nitro alias context. Summary:
- Using shared/ works because Nuxt handles the aliasing and import context for you. - For strictly server-only code, server/ is conceptually correct, but custom aliasing for userland files can be problematic in Nitro. - If you need to allow users to provide their own implementation and want a smooth developer experience, using shared/ is a practical workaround, even if it’s not strictly server-only. Just document that the file should not import client-side or Vue-specific code. If you need stricter server-only guarantees, you may need to wait for improvements in Nitro’s alias handling or explore alternative patterns, as the knowledge sources do not provide a more robust solution for dynamic server-only userland imports at this time. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@227872143281487872> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
_frdrk_
_frdrk_OP3mo ago
@kapa.ai it seems to only work when I pass an actual string in the dynamic import. If I put the same string in a variable, and use import(variableName) it doesnt work.
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You are correct—dynamic imports in JavaScript (and thus in Nuxt/Nitro) require a static string as the import path at build time. If you use a variable in import(variableName), the bundler (Vite, Webpack, or Rollup) cannot resolve the module at build time, and the import will fail at runtime. This is a limitation of how dynamic imports are processed in the build step. This behavior is also discussed in the context of Nuxt and Vue dynamic components: you cannot pass a variable to certain APIs expecting a static string, and similar limitations apply to dynamic imports Stack Overflow: dynamic import from assets Stack Overflow: dynamic <component>. Summary:
- import('some/static/path') works. - import(variableName) does not work unless the bundler can statically analyze all possible values of variableName. - This is a JavaScript and bundler limitation, not specific to Nuxt. If you need to support multiple possible imports, you can use a mapping object:
const importMap = {
foo: () => import('./foo'),
bar: () => import('./bar')
}
const module = await importMap[variableName]()
const importMap = {
foo: () => import('./foo'),
bar: () => import('./bar')
}
const module = await importMap[variableName]()
This pattern allows the bundler to see all possible import paths at build time. If you need more flexibility, you may need to rethink your architecture or use a different approach, as the knowledge sources do not provide a workaround for this limitation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@227872143281487872> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?