Is it possible to bundle and include npm/yarn packages in my server runtime code?

Has anyone gotten Webpack to work with Typescript for building the runtime index.js bundle?

I can only get it to output browser code, which the server can’t parse, or code which doesn’t seem complete. Setting Webpack’s "target": "node" option has no effect (still outputs browser code), and using "target": "es5" causes InitModule function not found. fatal error when the server tries to start.

Webpack is necessary since Typescript can’t natively bundle its code with node modules (like lodash). So you need to use Webpack to bundle it instead.

const path = require("path");

module.exports = {
    entry: "./src/main.ts",
    target: "es5",
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: "ts-loader",
                exclude: /node_modules/,
            },
        ],
    },
    resolve: {
        extensions: ['.ts', '.js'],
    },
    output: {
        path: path.resolve(__dirname, "build"),
        filename: "index.js",
    },
};

@jasontosh We’ve not yet experimented with other bundlers instead of the builtin features of the TypeScript compiler to bundle the code. Can you open a feature request on the nakama-common repo and we’ll take a look at what it looks like to add support for a tool like Webpack.

I should also mention that the JS runtime in Nakama server is not the Node runtime so you should not expect to be able to resolve modules through Node-style imports. This is why we recommend the vanilla TypeScript toolchain to bundle your code.

Ok, I created an issue for it: [Feature] Example or template using Webpack as bundling tool for Typescript runtime code · Issue #571 · heroiclabs/nakama · GitHub

Webpack should be able to bundle all dependencies and eliminate the imports entirely. I think. People say it can. :sweat_smile: I’m still learning. I’ll keep banging on it.

2 Likes

:grinning: if JS runtime can use many third part JS/TS libs easily, that would be exciting

A while back, I got the package to build with Webpack (and Babel), but the server still fails to start, saying it can’t find the InitModule function (details in the GitHub issue).

Seems like if the server was more flexible about how that function can be defined/discovered, maybe it would work? But I’m only guessing and haven’t yet looked at what the server code tries to do at start up.

I’ve found that it is easier to use Rollup instead to bundle the code in a way that can be used in Nakama. I’ve set up a template https://github.com/tailam1990/nakama-rollup-ts, perhaps you can find something useful there for a webpack setup. I have yet to be able to setup webpack correctly without InitModule being wrapped in IIFEs or other problems.

1 Like

Cool! Thank you for sharing your solution. I’ll have a look at it. :+1:

I finally got time to try this, and it worked! :flushed: I am able to import and use lodash and other things. Only change I had to make was to set the build target in tsconfig.json to “es5”.

Thank you, @tailam1990 for providing your example! :raised_hands:

We’ve also extended our Server Framework TypeScript setup to show you how to use Rollup to bundle and include npm/yarn packages in your server runtime code TypeScript Setup - Heroic Labs Documentation

2 Likes

Hi all,

sorry to unbury this topic, but I have problems with my project.

I followed the documentation to bundle with rollup, it seems to work fine, but only the main.ts file is bundled.
I have others files in src (match_handler, match_rpc etc…), and they are not bundle in the final file.

I didn’t know rollup and I’m quite new in ts, nodejs.

I used the source files from the github template.

Did I miss something?

EDIT : Should I add .bind(null) for each methods I declare? Is there a more convenient way?

thanks in advance

Hi, you should add imports i think

Hi,
this is exactly what I missed.
thx a lot!

1 Like

Hi there. I have my server running smoothly using rollup, babel, and docker, but I’m running into an issue when I try to include certain npm libraries.

For example, if I add papaparse (a CSV parser) to my project with “npm i papaparse”, and then do “npm build run” to see the code that Rollup is generating, I find this in the top line:

import require$$0 from 'stream';

For some reason, babel is correctly transpiling most of the code, but fails to transpile that import command. (Which then causes the Nakama server to fail when trying to import the JS code since that line is ES6.)

My setup is identical to the recommended setup from the Nakama typescript getting started guides.

rollup.config.js

import resolve from '@rollup/plugin-node-resolve';
import commonJS from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import babel from '@rollup/plugin-babel';
import typescript from '@rollup/plugin-typescript';
import pkg from './package.json';

const extensions = ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.es6', '.json', '.map'];

export default {
	input: './src/main.ts',
	external: ['nakama-runtime'],
	plugins: [
		// Allows node_modules resolution
		resolve({ extensions }),

		// Compile TypeScript
		typescript(),

		json(),

		// Resolve CommonJS modules
		commonJS({ extensions }),

		// Transpile to ES5
		babel({
			extensions,
			babelHelpers: 'bundled',
		}),
	],
	output: {
		file: pkg.main,
	},
};

babel.config.json

{
    "presets": [ "@babel/preset-env"],
}

Any idea what I need to do to get babel to work correctly? I’m assuming it has something to do with the fact that the code in question is in node_modules, but everything I’ve tried to fix it hasn’t worked.

Thanks!

this is fine, nakama javascript VM build on top of goja - GitHub - dop251/goja: ECMAScript/JavaScript engine in pure Go and stream is an abstract interface for working with streaming data in Node.js