Closed 0x0ece closed 4 years ago
This is common across all Typescript projects that use tsc (which nest does my default) instead of using a bundling tool (like webpack which nest is also compatible with). Even node projects by default depend on node_modules
to properly run. Without a major change to how Node works, or without using a bundler, this is not going to behave any differently.
I tried with webpack but I get the same result (change build in --webpack). Meaning, the content of dist is different, but the error is the same.
In #1706 the problem seemed that they had to ignore some modules to make sure webpack could complete. Here webpack works, but then same exact Error: Cannot find module '@nestjs/core'
as above.
Right, Nest's webpack configuration uses webpack-node-externals, which means that everything your applications uses requires()
for from the node_modules
directory is still necessary and not webpacked. In the issue you linked, Kamil adds some insights on to why webpacking the backend doesn't usually work out too well due to needing things like C++ bindings for some lower level connections like database packages and the use of packages like bcrypt
or argon2
for example.
You're always welcome to build your own webpack configuration that would bring everything into a single file, but Nest will not provide the config for that.
Oh ok, thank you for the insights. Closing this then.
@0x0ece How did you solve this problem?
@jmcdo29 I want to integrate it into my electron application and bring everything into a single file. How do I do that ?
I didn't solve, I'm not packing into 1 single js file. Sorry...
This is common across all Typescript projects that use tsc (which nest does my default) instead of using a bundling tool (like webpack which nest is also compatible with). Even node projects by default depend on
node_modules
to properly run. Without a major change to how Node works, or without using a bundler, this is not going to behave any differently.
Some contradictions arises, however. If nestjs was heavily designed with an "Angular" perspective, then this way of building is completely different. You may build an angular application (Typescript) and get a dist/
directory with all you need to serve it. Moreover, you don't even need node to serve it. Just put the dist/
directory in any webserver for it to be served.
To me, it should be an improvement for nestjs. Because as Angular, nestjs is heavily opinionated also. So having a bundler and produce an independent build will provide an extraordinary way of delivering nest applications. Adding to that, containers will get the benefits of simplifying and minimizing the deployment.
Today, you need to install dependencis, prune them for production, and moving node_modules around together with your dist. That's not a build, from my perspective. It's just a dev environment being served.
@gentunian the reason Angular can create this production build option is because of how the browser environment works. There's no dependencies on C++ bindings or python libraries, there's no worries about database connections, there's just JavaScript, HTML, and CSS. With Node, you have these C++ bindings in packages like pg
, bcrypt
, argon2
, sharp
and others. These bindings pose huge problems when it comes to using webpack/snowpack/rollup/
Heroku already manages this install, build, prune step for you. AWS is completely hands off and has multiple paths you could take (ECS, ECR, lambda, etc). Docker is another hands off approach and I have a sample tempalte here if you'd like to take a look using a multi-step build.
Nest's architecture is heavily inspired by Angular, that is and always will be true. But due to differences between the browser and node environment, providing the "right" build script to cover all cases (even all basic cases) would be difficult in its own right.
IF we were to attempt this (and that's a bit if) what do you say the build should do? Right now, build
calls tsc
or webpack
and transpiles the code from un-runnable TS to runnable JS code. What else, in your opinion, should happen?
@jmcdo29 good point. For one project I needed to make use of pkg
that internally searches for every use of require()
and bundles up a binary (not saying that nest should do that) and also tackles nodejs addons. I wonder if something similar for nest would make sense...
(edit to avoid getting people notified) I saw your docker template and I'm amazed by practically the same approach we take, this is what I'm using to ship docker images from nest apps:
FROM node:12-alpine as deps
WORKDIR /app
COPY package*.json .
RUN npm ci
FROM node:12-alpine as build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build && npm prune --production
FROM node:12-alpine
WORKDIR /app
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
EXPOSE 3000
CMD [ "node", "dist/main" ]
It might be interesting. It looks like pkg works on the compiled JS, so it could be a secondary step taken. It looks like pkg
also bundles in a node
runtime to the output file, which while it works, it also could end up causing bloat if you know you're going to run the code on a server with node
already installed. Definitely an idea to think about, but I don't see us implementing this anytime soon. Feel free to create a POC if you really want though :)
Might be necroposting, but you can do this with ncc by vercel:
ncc build ./dist/main.js -m -C -o ./ncc
node ./ncc/index.js
example: https://github.com/ishanuda/nestjs-ncc-bytenode/blob/main/server/package.json repo: https://github.com/vercel/ncc
I got an error with @mikro-orm/core
though trying this. mikro-orm
unreliably checks for versions being the same.
Bug Report
Build artifacts depend
node_modules
.This is analogous to #1706, but for Nestjs 7.
The issue seems different as it's not a building issue, but an issue after building succeeds. I tried to follow the discussion in #1706 but I couldn't find a fix. Can anyone provide a resolution?
Current behavior
Repro:
Expected behavior
After build, the artifacts in
dist
should run without depending onnode_modules
.Environment
(I'm on node12/macosx, but the same happens if I build within Docker)