The problem
I am using Phaser 3 html5 framework that runs on webpack. I am trying to make an offline game that would run on desktop or mobile apps, not a browser game, so I don't want to use the local storage or other in-memory databases. The players should be able to save the game, and the game would be stored in a DB file. I am trying to find the best solution to relational DB in my app.
What I tried:
I tried implementing sqlite3
, better-sqlite3
, postgres
and few other options, but nothing seems to be working. The client-side can't handle databases and is throwing errors. I also tried browserify
to bundle sqlite3
imports into binary and call it from the index.html
, but that also gave me errors:
(terminal) .src/ browserify server.js > bundle.js
.src/server.js:
const db = require('better-sqlite3')('game.db');
.src/bundle.js:
.src/index.html:
<script src="bundle.js></script>
error:
bundle.js:5638 Uncaught TypeError: The "original" argument must be of type Function
at promisify (bundle.js:5638:11)
at Object.<anonymous> (bundle.js:146:18)
at Object.<anonymous> (bundle.js:209:4)
at 4.../util (bundle.js:209:17)
at o (bundle.js:1:265)
at bundle.js:1:316
at Object.<anonymous> (bundle.js:74:29)
at Object.<anonymous> (bundle.js:88:4)
at 1.../../../../../../../usr/local/lib/node_modules/browserify/node_modules/is-buffer/index.js (bundle.js:88:17)
at o (bundle.js:1:265)
I would like to know if there is an easy way to create and use a relational database like SQLite3 or Postgres with NodeJS without dealing with browser limitations since the app won't run in the browser eventually. Please let me know if you have any insights on this. I am also sharing my webpack.config and tsconfig files for reference:
webpack config file
const path = require("path");
const webpack = require("webpack");
const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.config.base.js");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const LoadablePlugin = require("@loadable/webpack-plugin");
const clientConfig = {
entry: {
main: "./src/index.ts"
},
name: "client",
devtool: 'inline-source-map',
optimization: {
splitChunks: {
cacheGroups: {
phaser: {
test: /[\\/]node_modules[\\/]phaser[\\/]/,
name: "phaser",
chunks: "all",
},
}
}
},
output: {
path: path.resolve(__dirname, 'www'),
filename: "main.js"
},
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.json/,
type: "asset/resource",
exclude: /node_modules/,
},
],
},
devServer: {
historyApiFallback: true,
allowedHosts: 'all',
static: {
directory: path.resolve(__dirname, "./src"),
},
open: true,
hot: true,
port: 8080,
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, "src/index.html"),
minify: false
}),
new CleanWebpackPlugin(),
new LoadablePlugin({
outputAsset: false, // to avoid writing loadable-stats in the same output as client
writeToDisk: true,
filename: `${__dirname}/loadable-stats.json`,
}),
new webpack.LoaderOptionsPlugin({
// test: /\.xxx$/, // may apply this only for some modules
options: {
ts: {
configFileName : 'tsconfig.client.json'
}
}
}),
new CopyPlugin({
patterns: [
{
from: "static",
globOptions: {
// asset pack files are imported in code as modules
ignore: ["**/publicroot", "**/*-pack.json"]
}
}
]
}),
]
};
module.exports = merge(baseConfig, clientConfig);
tsconfig file
{
"extends": "./tsconfig.json",
"skipLibCheck": true,
"compilerOptions": {
"module": "ES6",
"target": "ES2022",
"outDir": "./www",
"rootDir": "./src",
"esModuleInterop": true,
"typeRoots": [
"node_modules/@types",
"node_module/phaser/types"
],
"types": [
"phaser", "node"
],
},
"include": [
"src/**/*",
"types/**/*"
]
}