FiveM is a modification for Grand Theft Auto V enabling you to play multiplayer on customized dedicated servers, powered by Cfx.re.
When you develop a FiveM server, you can create resource. Theses resources can be write in multiple langage Lua, C# and JavaScript. In this article we are going to see how to build a resource using TypeScript 
Type :
For typing our code, we will use two packages provided by CFX.re the company behind FiveM
- @citizenfx/client
- @citizenfx/server
These packages provided types for each native method usable inside client-side or server-side code.
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    // Location
    "outDir": "./dist",
    // Other
    "types": ["@citizenfx/client", "@types/node"],
    "lib": ["ES2020"],
    "strict": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["**/node_modules", "**/.test.ts"]
}
Bundle :
After the compilation of .ts files, you will have to create a bundle which going to be loaded and ran by FiveM server. Indeed, FiveM only allows require of native node.js package like path, fs, … 
To do it, we use the tool named rollup, it’s a JavaScript module bundler based on plugin system. I also explored other tools like vite, rspack, but it’s too complicated. An other tool which offers good performance will be turbopack a tool behind next bundling but it still inside next for the moment.
rollup.config.mjs
import typescript from "@rollup/plugin-typescript";
import commonjs from "@rollup/plugin-commonjs";
import resolve from "@rollup/plugin-node-resolve";
export default {
  input: "src/index.ts",
  output: {
    dir: "dist",
    format: "cjs",
    sourcemap: false,
  },
  plugins: [resolve(), typescript(), commonjs()],
};
package.json :
{
  ...
  "devDependencies": {
    "@citizenfx/client": "2.0.9282-1",
    "@rollup/plugin-commonjs": "^26.0.1",
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@rollup/plugin-typescript": "^11.1.6",
    "@types/node": "^20.14.12",
    "rollup": "^4.20.0",
    "tslib": "^2.6.3",
    "typescript": "^5.5.4"
  },
  ...
}
Exemple
init.ts
import { join } from "path"
export const init = () => {
    console.log("inited", join(".", "init.js"));
}
index.ts
import { init } from "./init"
on("onResourceStart", async (resName: string) => {
  if (resName === GetCurrentResourceName()) {
    init();
  }
});
After running rollup -c, you will have only one file :
'use strict';
var path = require('path');
const init = () => {
    console.log("inited", path.join(".", "init.js"));
};
on("onResourceStart", async (resName) => {
    if (resName === GetCurrentResourceName()) {
        init();
    }
});
 

 
    
Top comments (0)