-
Notifications
You must be signed in to change notification settings - Fork 35
This does not work with dynamic or conditional module imports #68
Comments
Almost all function bundling solutions have the concept of This covered the missing pieces when trying to parse the AST or use recursive We most likely need a higher level option for users to explicitly include/exclude files from the packaging step during the build |
Needed because netlify/zip-it-and-ship-it#68
An additional use case: some libraries create their source files at runtime or during This is a little different from the cases above because we crawl Node modules differently. Instead of using |
Bumping this issue, as it was the first problem I encountered when trying to use Netlify functions. It seems to me that the correct behaviour here would be to ignore modules that can't be resolved — if they fail at runtime, so be it (though as @ehmicky describes this is often used to detect the presence of optional dependencies, meaning 'failure' is generally intentional in these cases). Short of that, a warning could be printed to help track down the cause of those runtime errors. With the current behaviour, you have to jump through some very complex hoops to get widely-used packages like |
Possibly related to issue #205. |
Remix will need this (or they'll have to do some extra fanciness during the build). I've put together a simple example repo (without remix) that works locally, but not in production:
Here's what it looks like locally: |
Hi @kentcdodds, What's not currently supported are After cloning your repository, it looks your problem is different (see build logs). In order for Netlify Functions to work properly, you currently need a build command, otherwise those functions won't be bundled by |
Ah, thanks for clearing that up @ehmicky. So I've updated the project to make it an actual dynamic require and added a build command. Once dynamic requires are supported, then I'll get it updated to serve as an example :) Thanks! |
Thanks for the additional information @kentcdodds!
|
I'm not sure actually. All I know is the files need to be in a specific structure and require-able by that structure at runtime |
@ehmicky We just need an For example, other serverless functions like vercel have an option to indicate other files that are needed that you won't find by static analysis of requires: {
"includeFiles": ["remix.config.js", "build/**/*.js"]
} |
Little more background, when the remix request handler gets a request, it matches against the routes and then dynamically requires the "route loaders" (functions that fetch data server side for the view). We're considering changing our build step to turn all of that into static requires in the entry of the function, but at the moment it's dynamic. An |
Agree with this! Seems like such a low hanging fruit enabling the ability to bundle things such as content editable with Netlify CMS. |
Thanks a lot everyone for your feedback! We are looking into solving this problem and are considering different options. Whichever solution is chosen would need to allow including/excluding files both:
This raises the following questions:
@calavera mentioned #225 as a possible solution for this, providing it does solve those two questions. |
I vote the include/exclude should go in Redacted due to @ryanflorence's great points below |
Please note that when it comes to Functions' dependencies, The situation is different with the Netlify Functions files themselves (as opposed to the Netlify Functions dependencies). For those, we parse the Function's JavaScript code, look for top-level |
I think that's sufficient for remix. AFAIK, remix only dynamically requires user code. |
Regarding issue 1), couldn't we solve it by not requiring the module. If it's present in node_modules, add it. If it's not available, don't fail. |
Yes. Seems like the only place to do it, from your docs:
Only the app that's being deployed should have to worry about configuring this. In the case of Remix, as a dependency, we don't dynamically require any of our own modules, otherwise they wouldn't be dynamic! The requires are dynamic because we don't know the names of the files: they're supplied by the app. Additionally, apps get to configure where their "data loaders" live, so we wouldn't even be able to specify this information ourselves anyway. They're app modules. Another case is Prism.js. It does dynamic requires for plugins and themes. If I'm deploying a markdown blog with prism, I would definitely not want prism to be defining every possible file that could be required and then netlify deploying a bunch of code I don't use (and if those modules have side-effects, they'd likely break something). I think the only thing you need is an [build]
functions = "src"
include = [
"src/app/remix.config.js",
"src/app/build/**/*",
"src/app/node_modules/prisms/plugins/whatever.js"
] Seems a more natural place to configure would be for each function (other platforms I've used have this). I couldn't find anything similar in the docs, so I guess package.json would work? // functions/some-func/package.json
{
"netlify": {
"include": ["node_modules/prismjs/plugins/whatever.js"]
}
} |
Oh, just noticed this recommended directory structure at https://docs.netlify.com/functions/build-with-javascript/#unbundled-javascript-function-deploys
If that's the recommend structure, then I think the I don't think it needs to be much more complicated than that 😁 And to reiterate, I really don't think you want third party dependencies able to define behavior of a Netlify customer's deployment config 😬 Too many dragons there with module side-effects and unnecessarily inflating the size of the zip (and therefore cold starts, etc.). Then you'll need an "exclude" option to prevent that stuff, and now it's a deployment battle between the app and the dependencies. |
After poking around the code a bit, I think #225 is probably the right approach here :) |
Due to netlify/zip-it-and-ship-it#68, and because faunadb uses node-fetch, we have to explicitly add encoding as a dependency or the function fails to compile on Netlify.
I believe all the problems described here were addressed:
If there's any part of this thread that hasn't been addressed yet, please add a comment and I'll reopen the issue. Thanks! |
Some Node modules do this:
Or this:
Or this:
Or this:
A common example is
node-fetch
which conditionally requireencoding
.encoding
is only used with thetextConverted
method, which throws if it's missing.Another example is
@nestjs/graphql
which usesapollo-server-core
but does not declare it in its productiondependencies
.The reason why some modules might want to do this and not use
optionalDependencies
is to allow users to opt-in to installing specific modules.However this creates the following two issues with
zip-it-and-ship-it
. When the conditionalrequire()
is performed:zip-it-and-ship-it
always bundles the dependency. Users should have a way to exclude such modules in the archive if they want to.zip-it-and-ship-it
never bundles the dependency. This is because we find nested dependencies by only checking thepackage.json
dependencies
,peerDependencies
andoptionalDependencies
keys (as opposed to look forrequire()
statements). Users should have a way to include such modules in the archive if they want to.The current workaround are (for the points above):
npm install
the dependencynpm install
the dependency and add a nooprequire()
call in its function file code.However this feels hacky, so we should think of a better solution.
The text was updated successfully, but these errors were encountered: