What's the best way to package a node-js server in...
# javascript
s
What's the best way to package a node-js server in a docker container? I'm doing the following: 1. Run a full project clean 2. Build only the server I want to package 3. Grabbing the
<root project>/build/js
dir and putting it in the docker container. The problem is that this folder contains EVERY single library that any project in my entire workspace touches. So my docker image is 400 MB, when it only needs to be 20 or 30 MB. Is there any way to JUST package exactly the used dependencies?
t
Build only the server I want to package
On this step you will install all NPM dependencies of your project
s
yes. I suppose there is no reasonable way around that?
t
Simplest solution, which I see: 1. Build app 2. Copy resulted
js
file and
package.json
(in IR resulted file can be single) in separate folder 3. Run
npm i
4. Pack folder in docker container
Step 3 can be skipped, if you can bundle dependencies inside resulted
js
file
s
I'd have to also move over any of the project dependency folders as well
Now that i think about this though... I should be able to make a gradle task that can detect those and move them over...
Yes - I do have to get the project dependency folders as well... Even though the IR compiler has the js files there locally, the NPM dependencies they references aren't there.
t
Even though the IR compiler has the js files there locally
It will be safety to build single JS file
s
how do I do this?
The browser can do this with webpack, but how would I do this using a nodejs target?
@turansky ?
t
The browser can do this with webpack, but how would I do this using a nodejs target?
The same way 🙂
s
Webpack is automatically applied to browser in kotlin. Is there a way for me to turn it on for nodejs?
t
Copy code
kotlin.js.ir.output.granularity=whole-program
to build single JS file
Webpack is automatically applied to browser in kotlin. Is there a way for me to turn it on for nodejs?
browser
target for Kotlin/JS (to activate distribution) + node configuration for webpack (for valid
globalThis
)
s
Copy code
kotlin.js.ir.output.granularity=whole-program
It looks like the file this creates doesn't contain the
node_modules
dependencies.
browser
target for Kotlin/JS (to activate distribution) + node configuration for webpack (for valid
globalThis
) (edited)
I don't follow what you mean here
t
It looks like the file this creates doesn’t contain the
node_modules
dependencies.
Yes, it’s classic NodeJS distribution mode
I don’t follow what you mean here
Copy code
kotlin.js {
    browser {
        commonWebpackConfig {
            globalThis = "globals" // for node
        }
    }
}
s
ok - I see what you mean
I ended up creating a gradle plugin that traverses across all of a projects project dependencies grabbing the npm dependencies, and then recreates a slim version that can be easily deployed
g
Wouldn’t be better to use minimized resulting js after all obfuscation/tree shaking with all dependencies bundled? it sounds a bit more efficient to pack in docker
t
Both options can be useful. Bonus of external dependencies - dependencies refresh, without rebuild
And faster build 🙂
s
Well - the other thing, if you are using a function or serverless platform to run your code, which I am, supposedly the startup time is much worse for a single file, than lazily with many small files.
👍 1
g
Good point 👍 I really curious is it possible (for example with webpack) to have tree-shaking and obfuscation on dependency js file and still have lazy initialisation
s
The problem with cold start times is that even though things is less the code actually initializing during it's running phase, it's that it has to 1. 100% of your application has to be loaded from disk. The size of your app becomes a limiting factor and 2. All that js code has to be interpreted, even if it's not run (I think?).
in an ideal world with a JS server, I would only create endpoints / routes during initialization. Any dependencies beyond express, I would
require
inside of the endpoint call and then use. This would yield the best times. Currently this isn't reasonably possible with kotlin js unless you separate your code into an http module and a separate module for actually doing the logic of the endpoints. Even then, I'm not certain how it will work
g
Yes, I see, it’s an issue of deferred module initialization, which is not really work with Kotlin out of the box I feel that app size by itself shouldn’t be a huge issue by itself, but interpretation and overall init looks like a bigger problem. After all app size limited mostly by disk speed, everything else is runtime init speed. But in this case why there is any difference in case of Kotlin app when you have single file and your app file + dependencies in separate files if program anyway init on start
supposedly the startup time is much worse for a single file, than lazily with many small files.
Really curious how different it is without on demand modules loading