2020-04-01 19:47:33 +00:00
|
|
|
import * as fs from "fs";
|
2020-04-09 17:26:56 +00:00
|
|
|
import * as util from "util";
|
2021-03-17 13:00:35 +00:00
|
|
|
import * as path from "path";
|
2021-03-17 14:38:56 +00:00
|
|
|
import * as child_process from "child_process";
|
2020-08-08 22:08:56 +00:00
|
|
|
|
2021-03-17 18:41:51 +00:00
|
|
|
import {GeneratedAssetPlugin} from "./webpack/GeneratedAssetPlugin";
|
|
|
|
|
2021-03-17 17:25:04 +00:00
|
|
|
import { DefinePlugin, Configuration, } from "webpack";
|
2021-03-17 12:28:27 +00:00
|
|
|
|
|
|
|
import { Plugin as SvgSpriteGenerator } from "webpack-svg-sprite-generator";
|
2021-03-17 18:41:51 +00:00
|
|
|
import ManifestGenerator from "./webpack/ManifestPlugin";
|
|
|
|
import HtmlWebpackInlineSourcePlugin from "./webpack/HtmlWebpackInlineSource";
|
2021-03-22 16:00:11 +00:00
|
|
|
import TranslateableWebpackPlugin from "./tools/trgen/webpack/Plugin";
|
2021-03-17 12:28:27 +00:00
|
|
|
|
2021-03-17 18:41:51 +00:00
|
|
|
import ZipWebpackPlugin from "zip-webpack-plugin";
|
2021-03-17 12:28:27 +00:00
|
|
|
import HtmlWebpackPlugin from "html-webpack-plugin";
|
2021-03-17 18:41:51 +00:00
|
|
|
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
|
|
|
import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
|
|
|
|
import TerserPlugin from "terser-webpack-plugin";
|
|
|
|
import CopyWebpackPlugin from "copy-webpack-plugin";
|
2021-03-17 12:28:27 +00:00
|
|
|
|
|
|
|
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
|
|
|
|
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
|
2020-03-27 22:36:14 +00:00
|
|
|
|
2020-04-01 19:47:33 +00:00
|
|
|
export let isDevelopment = process.env.NODE_ENV === 'development';
|
2020-04-02 15:40:09 +00:00
|
|
|
console.log("Webpacking for %s (%s)", isDevelopment ? "development" : "production", process.env.NODE_ENV || "NODE_ENV not specified");
|
2021-03-16 15:40:17 +00:00
|
|
|
|
2021-03-17 18:41:51 +00:00
|
|
|
interface LocalBuildInfo {
|
|
|
|
target: "client" | "web",
|
|
|
|
mode: "debug" | "release",
|
|
|
|
|
|
|
|
gitVersion: string,
|
|
|
|
gitTimestamp: number,
|
|
|
|
|
|
|
|
unixTimestamp: number,
|
|
|
|
localTimestamp: string
|
|
|
|
}
|
|
|
|
|
|
|
|
let localBuildInfo: LocalBuildInfo;
|
|
|
|
const generateLocalBuildInfo = async (target: string): Promise<LocalBuildInfo> => {
|
|
|
|
let info: LocalBuildInfo = {} as any;
|
|
|
|
|
|
|
|
info.target = target as any;
|
|
|
|
info.mode = isDevelopment ? "debug" : "release";
|
2020-04-01 19:47:33 +00:00
|
|
|
|
2021-03-17 18:41:51 +00:00
|
|
|
{
|
|
|
|
const gitRevision = fs.readFileSync(path.join(__dirname, ".git", "HEAD")).toString();
|
|
|
|
if(gitRevision.indexOf("/") === -1) {
|
2021-05-16 10:32:19 +00:00
|
|
|
info.gitVersion = (gitRevision || "00000000").substr(0, 8);
|
2021-03-17 18:41:51 +00:00
|
|
|
} else {
|
2021-05-16 10:32:19 +00:00
|
|
|
info.gitVersion = fs.readFileSync(path.join(__dirname, ".git", gitRevision.substr(5).trim())).toString().substr(0, 8);
|
2021-03-17 18:41:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { stdout } = await util.promisify(child_process.exec)("git show -s --format=%ct");
|
|
|
|
info.gitTimestamp = parseInt(stdout.toString());
|
|
|
|
if(isNaN(info.gitTimestamp)) {
|
|
|
|
throw "failed to parse timestamp '" + stdout.toString() + "'";
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Failed to get commit timestamp: %o", error);
|
|
|
|
throw "failed to get commit timestamp";
|
2021-03-16 15:40:17 +00:00
|
|
|
}
|
2020-04-09 17:26:56 +00:00
|
|
|
}
|
2021-03-16 15:40:17 +00:00
|
|
|
|
2021-03-17 18:41:51 +00:00
|
|
|
info.unixTimestamp = Date.now();
|
|
|
|
info.localTimestamp = new Date().toString();
|
|
|
|
|
|
|
|
return info;
|
|
|
|
};
|
|
|
|
|
|
|
|
const generateDefinitions = async (target: string) => {
|
2020-04-01 19:47:33 +00:00
|
|
|
return {
|
|
|
|
"__build": {
|
2020-04-02 15:40:09 +00:00
|
|
|
target: JSON.stringify(target),
|
2020-04-01 19:47:33 +00:00
|
|
|
mode: JSON.stringify(isDevelopment ? "debug" : "release"),
|
2021-03-17 18:41:51 +00:00
|
|
|
version: JSON.stringify(localBuildInfo.gitVersion),
|
|
|
|
timestamp: localBuildInfo.gitTimestamp,
|
2021-03-20 15:39:50 +00:00
|
|
|
entry_chunk_name: JSON.stringify("main-app")
|
2020-04-01 19:47:33 +00:00
|
|
|
} as BuildDefinitions
|
2021-03-17 13:00:35 +00:00
|
|
|
} as any;
|
2020-07-13 09:29:16 +00:00
|
|
|
};
|
|
|
|
|
2021-03-17 12:28:27 +00:00
|
|
|
const generateIndexPlugin = (target: "web" | "client"): HtmlWebpackPlugin => {
|
|
|
|
const options: HtmlWebpackPlugin.Options & { inlineSource?: RegExp | string } = {};
|
|
|
|
|
|
|
|
options.cache = true;
|
|
|
|
options.chunks = ["loader"];
|
|
|
|
options.inject = false;
|
|
|
|
options.template = path.join(__dirname, "loader", "index.ejs");
|
|
|
|
options.templateParameters = { buildTarget: target };
|
|
|
|
options.scriptLoading = "defer";
|
|
|
|
|
|
|
|
if(!isDevelopment) {
|
|
|
|
options.minify = {
|
|
|
|
html5: true,
|
|
|
|
|
|
|
|
collapseWhitespace: true,
|
|
|
|
removeComments: true,
|
|
|
|
removeRedundantAttributes: true,
|
|
|
|
removeScriptTypeAttributes: true,
|
|
|
|
removeTagWhitespace: true,
|
|
|
|
minifyCSS: true,
|
|
|
|
minifyJS: true,
|
|
|
|
minifyURLs: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
options.inlineSource = /\.(js|css)$/;
|
|
|
|
}
|
|
|
|
return new HtmlWebpackPlugin(options);
|
|
|
|
}
|
|
|
|
|
2021-03-17 18:41:51 +00:00
|
|
|
export const config = async (env: any, target: "web" | "client"): Promise<Configuration & { devServer: any }> => {
|
|
|
|
localBuildInfo = await generateLocalBuildInfo(target);
|
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
const translateablePlugin = new TranslateableWebpackPlugin({ assetName: "translations.json" });
|
2020-04-01 13:36:37 +00:00
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
return {
|
|
|
|
entry: {
|
2021-03-17 17:25:04 +00:00
|
|
|
"loader": "./loader/app/index.ts",
|
2021-03-20 14:10:16 +00:00
|
|
|
"modal-external": "./shared/js/entry-points/ModalWindow.ts",
|
2021-03-17 14:38:56 +00:00
|
|
|
},
|
2021-03-17 13:00:35 +00:00
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
devtool: isDevelopment ? "inline-source-map" : "source-map",
|
|
|
|
mode: isDevelopment ? "development" : "production",
|
|
|
|
plugins: [
|
|
|
|
new CleanWebpackPlugin(),
|
2021-03-17 18:41:51 +00:00
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
new DefinePlugin(await generateDefinitions(target)),
|
2021-03-17 18:41:51 +00:00
|
|
|
new GeneratedAssetPlugin({
|
|
|
|
customFiles: [
|
|
|
|
{
|
|
|
|
assetName: "buildInfo.json",
|
|
|
|
content: JSON.stringify(localBuildInfo)
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}),
|
|
|
|
new ManifestGenerator({
|
|
|
|
outputFileName: "manifest.json",
|
|
|
|
context: __dirname
|
|
|
|
}),
|
2021-03-17 13:00:35 +00:00
|
|
|
|
2021-03-17 17:25:04 +00:00
|
|
|
new CopyWebpackPlugin({
|
|
|
|
patterns: [
|
2021-03-17 17:52:35 +00:00
|
|
|
{
|
|
|
|
from: path.join(__dirname, "shared", "img"),
|
|
|
|
to: 'img',
|
|
|
|
globOptions: {
|
|
|
|
ignore: [
|
|
|
|
'**/client-icons/**',
|
2021-03-17 19:52:52 +00:00
|
|
|
//'**/style/**',
|
2021-03-17 17:52:35 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
target === "web" ? { from: path.join(__dirname, "shared", "i18n"), to: 'i18n' } : undefined,
|
2021-03-17 17:25:04 +00:00
|
|
|
{ from: path.join(__dirname, "shared", "audio"), to: 'audio' }
|
2021-03-17 17:52:35 +00:00
|
|
|
].filter(e => !!e)
|
2021-03-17 17:25:04 +00:00
|
|
|
}),
|
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
new MiniCssExtractPlugin({
|
2021-03-17 17:52:35 +00:00
|
|
|
filename: isDevelopment ? "css/[name].[contenthash].css" : "css/[contenthash].css",
|
|
|
|
chunkFilename: isDevelopment ? "css/[name].[contenthash].css" : "css/[contenthash].css",
|
2021-03-17 17:32:03 +00:00
|
|
|
ignoreOrder: true,
|
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
}),
|
|
|
|
new SvgSpriteGenerator({
|
|
|
|
dtsOutputFolder: path.join(__dirname, "shared", "svg-sprites"),
|
2021-03-17 18:41:51 +00:00
|
|
|
publicPath: "/",
|
2021-03-17 14:38:56 +00:00
|
|
|
configurations: {
|
|
|
|
"client-icons": {
|
|
|
|
folder: path.join(__dirname, "shared", "img", "client-icons"),
|
|
|
|
cssClassPrefix: "client-",
|
|
|
|
cssOptions: [
|
|
|
|
{
|
|
|
|
scale: 1,
|
|
|
|
selector: ".icon",
|
|
|
|
unit: "px"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
scale: 1.5,
|
|
|
|
selector: ".icon_x24",
|
|
|
|
unit: "px"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
scale: 2,
|
|
|
|
selector: ".icon_x32",
|
|
|
|
unit: "px"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
scale: 1,
|
|
|
|
selector: ".icon_em",
|
|
|
|
unit: "em"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
dtsOptions: {
|
|
|
|
enumName: "ClientIcon",
|
|
|
|
classUnionName: "ClientIconClass",
|
|
|
|
module: false
|
2020-08-08 22:08:56 +00:00
|
|
|
}
|
2021-03-23 12:42:32 +00:00
|
|
|
},
|
|
|
|
"country-flags": {
|
|
|
|
folder: path.join(__dirname, "shared", "img", "country-flags"),
|
|
|
|
cssClassPrefix: "flag-",
|
|
|
|
cssOptions: [
|
|
|
|
{
|
|
|
|
scale: 1,
|
|
|
|
selector: ".flag_em",
|
|
|
|
unit: "em"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
dtsOptions: {
|
|
|
|
enumName: "CountryFlag",
|
|
|
|
classUnionName: "CountryFlagClass",
|
|
|
|
module: false
|
|
|
|
}
|
2020-08-08 22:08:56 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-17 14:38:56 +00:00
|
|
|
}),
|
2021-03-17 13:00:35 +00:00
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
generateIndexPlugin(target),
|
|
|
|
new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin),
|
2021-03-17 13:00:35 +00:00
|
|
|
|
2021-03-17 17:25:04 +00:00
|
|
|
translateablePlugin,
|
2021-03-17 14:38:56 +00:00
|
|
|
//new BundleAnalyzerPlugin(),
|
2021-03-17 18:41:51 +00:00
|
|
|
|
|
|
|
env.package ? new ZipWebpackPlugin({
|
|
|
|
path: path.join(__dirname, "dist-package"),
|
2021-03-22 16:00:11 +00:00
|
|
|
filename: `${target === "web" ? "TeaWeb" : "TeaClient"}-${isDevelopment ? "development" : "release"}-${localBuildInfo.gitVersion}.zip`,
|
2021-03-17 18:41:51 +00:00
|
|
|
}) : undefined
|
2021-03-17 14:38:56 +00:00
|
|
|
].filter(e => !!e),
|
2020-08-05 16:25:08 +00:00
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
module: {
|
|
|
|
rules: [
|
|
|
|
{
|
|
|
|
test: /\.(s[ac]|c)ss$/,
|
|
|
|
use: [
|
|
|
|
//'style-loader',
|
|
|
|
{
|
|
|
|
loader: MiniCssExtractPlugin.loader,
|
|
|
|
options: {
|
2021-03-17 17:32:03 +00:00
|
|
|
esModule: false,
|
2021-03-17 14:38:56 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
loader: 'css-loader',
|
|
|
|
options: {
|
|
|
|
modules: {
|
|
|
|
mode: "local",
|
|
|
|
localIdentName: isDevelopment ? "[path][name]__[local]--[hash:base64:5]" : "[hash:base64]",
|
|
|
|
},
|
|
|
|
sourceMap: isDevelopment
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
2021-03-17 17:32:03 +00:00
|
|
|
loader: "postcss-loader"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
loader: "sass-loader",
|
2021-03-17 14:38:56 +00:00
|
|
|
options: {
|
|
|
|
sourceMap: isDevelopment
|
|
|
|
}
|
2020-03-27 22:36:14 +00:00
|
|
|
}
|
2021-03-17 14:38:56 +00:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
test: /\.tsx?$/,
|
|
|
|
exclude: /node_modules/,
|
2020-03-27 22:36:57 +00:00
|
|
|
|
2021-03-17 14:38:56 +00:00
|
|
|
use: [
|
|
|
|
{
|
|
|
|
loader: "babel-loader",
|
|
|
|
options: {
|
|
|
|
presets: ["@babel/preset-env"]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
loader: "ts-loader",
|
|
|
|
options: {
|
|
|
|
context: __dirname,
|
|
|
|
colors: true,
|
|
|
|
getCustomTransformers: program => ({
|
2021-03-22 16:00:11 +00:00
|
|
|
before: [ translateablePlugin.createTypeScriptTransformer(program) ]
|
2021-03-17 14:38:56 +00:00
|
|
|
}),
|
|
|
|
transpileOnly: isDevelopment
|
|
|
|
}
|
2020-03-27 22:36:57 +00:00
|
|
|
}
|
2021-03-17 14:38:56 +00:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
test: /\.was?t$/,
|
|
|
|
use: [
|
|
|
|
"./webpack/WatLoader.js"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
test: /\.html$/i,
|
2021-03-22 16:00:11 +00:00
|
|
|
use: [ translateablePlugin.createTemplateLoader() ],
|
2021-03-17 14:38:56 +00:00
|
|
|
type: "asset/source",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
test: /ChangeLog\.md$/i,
|
|
|
|
type: "asset/source",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
test: /\.svg$/,
|
2021-03-23 14:13:51 +00:00
|
|
|
use: [{
|
|
|
|
loader: '@svgr/webpack',
|
|
|
|
options: {
|
|
|
|
svgoConfig: {
|
|
|
|
plugins: {
|
|
|
|
removeViewBox: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}],
|
2021-03-17 14:38:56 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
test: /\.(png|jpg|jpeg|gif)?$/,
|
2021-03-17 17:52:35 +00:00
|
|
|
type: "asset/resource",
|
|
|
|
generator: {
|
|
|
|
filename: 'img/[hash][ext][query]'
|
|
|
|
}
|
2021-03-17 14:38:56 +00:00
|
|
|
},
|
|
|
|
]
|
|
|
|
} as any,
|
|
|
|
resolve: {
|
|
|
|
extensions: ['.tsx', '.ts', '.js', ".scss"],
|
|
|
|
alias: {
|
|
|
|
"vendor/xbbcode": path.resolve(__dirname, "vendor/xbbcode/src"),
|
|
|
|
"tc-events": path.resolve(__dirname, "vendor/TeaEventBus/src/index.ts"),
|
|
|
|
"tc-services": path.resolve(__dirname, "vendor/TeaClientServices/src/index.ts"),
|
2020-08-22 19:20:25 +00:00
|
|
|
},
|
2021-03-24 15:56:09 +00:00
|
|
|
fallback: {
|
|
|
|
stream: "stream-browserify",
|
|
|
|
crypto: "crypto-browserify",
|
|
|
|
buffer: "buffer"
|
|
|
|
}
|
2021-03-17 14:38:56 +00:00
|
|
|
},
|
|
|
|
externals: [
|
|
|
|
{"tc-loader": "window loader"}
|
|
|
|
],
|
|
|
|
output: {
|
2021-03-17 17:52:35 +00:00
|
|
|
filename: isDevelopment ? "js/[name].[contenthash].js" : "js/[contenthash].js",
|
|
|
|
chunkFilename: isDevelopment ? "js/[name].[contenthash].js" : "js/[contenthash].js",
|
|
|
|
path: path.resolve(__dirname, "dist"),
|
|
|
|
publicPath: "/"
|
2021-03-17 14:38:56 +00:00
|
|
|
},
|
|
|
|
performance: {
|
|
|
|
hints: false
|
|
|
|
},
|
|
|
|
optimization: {
|
|
|
|
splitChunks: {
|
|
|
|
chunks: "all",
|
|
|
|
maxSize: 512 * 1024
|
2021-03-14 18:39:08 +00:00
|
|
|
},
|
2021-03-17 14:38:56 +00:00
|
|
|
minimize: !isDevelopment,
|
|
|
|
minimizer: [
|
|
|
|
new TerserPlugin(),
|
|
|
|
new CssMinimizerPlugin()
|
|
|
|
]
|
2020-07-17 21:56:20 +00:00
|
|
|
},
|
2021-03-17 14:38:56 +00:00
|
|
|
devServer: {
|
2021-03-17 17:52:35 +00:00
|
|
|
publicPath: "/",
|
2021-03-17 14:38:56 +00:00
|
|
|
contentBase: path.join(__dirname, 'dist'),
|
|
|
|
writeToDisk: true,
|
2021-03-17 17:25:04 +00:00
|
|
|
compress: true,
|
2021-03-23 14:13:51 +00:00
|
|
|
|
|
|
|
/* hot dosn't work because of our loader */
|
2021-03-17 17:25:04 +00:00
|
|
|
hot: false,
|
2021-03-23 14:13:51 +00:00
|
|
|
hotOnly: false,
|
|
|
|
|
2021-03-17 17:25:04 +00:00
|
|
|
liveReload: false,
|
2021-03-30 09:20:27 +00:00
|
|
|
inline: false,
|
|
|
|
|
2021-05-17 20:53:03 +00:00
|
|
|
host: "0.0.0.0",
|
2021-03-30 09:20:27 +00:00
|
|
|
https: process.env["serve_https"] === "1"
|
2020-04-01 19:47:33 +00:00
|
|
|
},
|
2021-03-17 14:38:56 +00:00
|
|
|
};
|
|
|
|
};
|