mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 10:53:31 +00:00
166ef92970
Create base components with shared styles, as start of make ui better. For now shoul look same but underhood new copoments are used. This should be first PR that handle this and many more comes. I am in rush due conflict with other ppl, but should work as i tested. Testing again and look at structure Main goal i have global css not scope in component die loading times and size of elements. (Modal due nature of lit and shadow dom is exception, maybe later find better way). Documenting the components will happen later as base components establish their usage.
303 lines
8.6 KiB
JavaScript
303 lines
8.6 KiB
JavaScript
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
import fs from "fs/promises";
|
|
import HtmlWebpackPlugin from "html-webpack-plugin";
|
|
import webpack from "webpack";
|
|
import CopyPlugin from "copy-webpack-plugin";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
async function checkResourcesCopied(sourceDir, targetDir) {
|
|
async function checkDir(source, target) {
|
|
let items;
|
|
try {
|
|
items = await fs.readdir(source, { withFileTypes: true });
|
|
} catch (error) {
|
|
console.error(`Error reading directory ${source}:`, error);
|
|
return false;
|
|
}
|
|
for (const item of items) {
|
|
const sourcePath = path.join(source, item.name);
|
|
const targetPath = path.join(target, item.name);
|
|
if (item.isDirectory()) {
|
|
try {
|
|
await fs.access(targetPath);
|
|
} catch (error) {
|
|
// Target directory does not exist.
|
|
return false;
|
|
}
|
|
const exists = await checkDir(sourcePath, targetPath);
|
|
if (!exists) return false;
|
|
} else if (item.isFile()) {
|
|
try {
|
|
await fs.access(targetPath);
|
|
} catch (error) {
|
|
// Target file does not exist.
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return checkDir(sourceDir, targetDir);
|
|
}
|
|
export default async (env, argv) => {
|
|
const isProduction = argv.mode === "production";
|
|
|
|
return {
|
|
entry: "./src/client/Main.ts",
|
|
output: {
|
|
publicPath: "/",
|
|
filename: "js/[name].[contenthash].js", // Added content hash
|
|
path: path.resolve(__dirname, "static"),
|
|
clean: isProduction,
|
|
},
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.bin$/,
|
|
type: "asset/resource", // Changed from raw-loader
|
|
generator: {
|
|
filename: "binary/[name].[contenthash][ext]", // Added content hash
|
|
},
|
|
},
|
|
{
|
|
test: /\.txt$/,
|
|
type: "asset/resource", // Changed from raw-loader
|
|
generator: {
|
|
filename: "text/[name].[contenthash][ext]", // Added content hash
|
|
},
|
|
},
|
|
{
|
|
test: /\.ts$/,
|
|
use: "ts-loader",
|
|
exclude: /node_modules/,
|
|
},
|
|
{
|
|
test: /\.css$/,
|
|
use: [
|
|
"style-loader",
|
|
{
|
|
loader: "css-loader",
|
|
options: {
|
|
importLoaders: 1,
|
|
},
|
|
},
|
|
{
|
|
loader: "postcss-loader",
|
|
options: {
|
|
postcssOptions: {
|
|
plugins: ["tailwindcss", "autoprefixer"],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
test: /\.(png|jpe?g|gif)$/i,
|
|
type: "asset/resource",
|
|
generator: {
|
|
filename: "images/[name].[contenthash][ext]", // Added content hash
|
|
},
|
|
},
|
|
{
|
|
test: /\.html$/,
|
|
use: ["html-loader"],
|
|
},
|
|
{
|
|
test: /\.svg$/,
|
|
type: "asset/resource", // Changed from asset/inline for caching
|
|
generator: {
|
|
filename: "images/[name].[contenthash][ext]", // Added content hash
|
|
},
|
|
},
|
|
{
|
|
test: /\.(woff|woff2|eot|ttf|otf)$/,
|
|
type: "asset/resource", // Changed from file-loader
|
|
generator: {
|
|
filename: "fonts/[name].[contenthash][ext]", // Added content hash and fixed path
|
|
},
|
|
},
|
|
],
|
|
},
|
|
resolve: {
|
|
extensions: [".tsx", ".ts", ".js"],
|
|
alias: {
|
|
"protobufjs/minimal": path.resolve(
|
|
__dirname,
|
|
"node_modules/protobufjs/minimal.js",
|
|
),
|
|
},
|
|
},
|
|
plugins: [
|
|
new HtmlWebpackPlugin({
|
|
template: "./src/client/index.html",
|
|
filename: "index.html",
|
|
// Add optimization for HTML
|
|
minify: isProduction
|
|
? {
|
|
collapseWhitespace: true,
|
|
removeComments: true,
|
|
removeRedundantAttributes: true,
|
|
removeScriptTypeAttributes: true,
|
|
removeStyleLinkTypeAttributes: true,
|
|
useShortDoctype: true,
|
|
}
|
|
: false,
|
|
}),
|
|
new webpack.DefinePlugin({
|
|
"process.env.WEBSOCKET_URL": JSON.stringify(
|
|
isProduction ? "" : "localhost:3000",
|
|
),
|
|
}),
|
|
new webpack.DefinePlugin({
|
|
"process.env.GAME_ENV": JSON.stringify(isProduction ? "prod" : "dev"),
|
|
}),
|
|
...(await (async () => {
|
|
if (isProduction) {
|
|
return [
|
|
new CopyPlugin({
|
|
patterns: [
|
|
{
|
|
from: "resources",
|
|
to: ".",
|
|
noErrorOnMissing: true,
|
|
},
|
|
],
|
|
options: { concurrency: 100 },
|
|
}),
|
|
];
|
|
} else {
|
|
const resourcesDir = path.resolve(__dirname, "resources");
|
|
const targetDir = path.resolve(__dirname, "static");
|
|
const allExist = await checkResourcesCopied(resourcesDir, targetDir);
|
|
if (allExist) {
|
|
console.log(
|
|
"[CopyPlugin] Skipped: All resources already exist in static/.",
|
|
);
|
|
return []; // Skip CopyPlugin if all resources are present.
|
|
} else {
|
|
console.log(
|
|
"[CopyPlugin] Copying missing resources to static/ ...",
|
|
);
|
|
return [
|
|
new CopyPlugin({
|
|
patterns: [
|
|
{
|
|
from: "resources",
|
|
to: ".",
|
|
noErrorOnMissing: true,
|
|
},
|
|
],
|
|
options: { concurrency: 100 },
|
|
}),
|
|
];
|
|
}
|
|
}
|
|
})()),
|
|
],
|
|
optimization: {
|
|
// Add optimization configuration for better caching
|
|
runtimeChunk: "single",
|
|
splitChunks: {
|
|
cacheGroups: {
|
|
vendor: {
|
|
test: /[\\/]node_modules[\\/]/,
|
|
name: "vendors",
|
|
chunks: "all",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
devServer: isProduction
|
|
? {}
|
|
: {
|
|
devMiddleware: { writeToDisk: true },
|
|
static: {
|
|
directory: path.join(__dirname, "static"),
|
|
},
|
|
historyApiFallback: true,
|
|
compress: true,
|
|
port: 9000,
|
|
proxy: [
|
|
// WebSocket proxies
|
|
{
|
|
context: ["/socket"],
|
|
target: "ws://localhost:3000",
|
|
ws: true,
|
|
changeOrigin: true,
|
|
logLevel: "debug",
|
|
},
|
|
// Worker WebSocket proxies - using direct paths without /socket suffix
|
|
{
|
|
context: ["/w0"],
|
|
target: "ws://localhost:3001",
|
|
ws: true,
|
|
secure: false,
|
|
changeOrigin: true,
|
|
logLevel: "debug",
|
|
},
|
|
{
|
|
context: ["/w1"],
|
|
target: "ws://localhost:3002",
|
|
ws: true,
|
|
secure: false,
|
|
changeOrigin: true,
|
|
logLevel: "debug",
|
|
},
|
|
{
|
|
context: ["/w2"],
|
|
target: "ws://localhost:3003",
|
|
ws: true,
|
|
secure: false,
|
|
changeOrigin: true,
|
|
logLevel: "debug",
|
|
},
|
|
// Worker proxies for HTTP requests
|
|
{
|
|
context: ["/w0"],
|
|
target: "http://localhost:3001",
|
|
pathRewrite: { "^/w0": "" },
|
|
secure: false,
|
|
changeOrigin: true,
|
|
logLevel: "debug",
|
|
},
|
|
{
|
|
context: ["/w1"],
|
|
target: "http://localhost:3002",
|
|
pathRewrite: { "^/w1": "" },
|
|
secure: false,
|
|
changeOrigin: true,
|
|
logLevel: "debug",
|
|
},
|
|
{
|
|
context: ["/w2"],
|
|
target: "http://localhost:3003",
|
|
pathRewrite: { "^/w2": "" },
|
|
secure: false,
|
|
changeOrigin: true,
|
|
logLevel: "debug",
|
|
},
|
|
// Original API endpoints
|
|
{
|
|
context: [
|
|
"/api/env",
|
|
"/api/game",
|
|
"/api/public_lobbies",
|
|
"/api/join_game",
|
|
"/api/start_game",
|
|
"/api/create_game",
|
|
"/api/archive_singleplayer_game",
|
|
"/api/auth/callback",
|
|
"/api/auth/discord",
|
|
],
|
|
target: "http://localhost:3000",
|
|
secure: false,
|
|
changeOrigin: true,
|
|
},
|
|
],
|
|
},
|
|
};
|
|
};
|