From 479168c26e45968f1430185bbd0e6935a0dedf88 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Thu, 9 Apr 2020 19:26:56 +0200 Subject: [PATCH] Added WebPack to the default `npm start web` starter. App could not be started out of the box (only PHP is required) --- file.ts | 89 +++++++++++++++++++++++++++------------- package.json | 10 +++-- webpack-client.config.ts | 31 +++++++------- webpack-web.config.ts | 23 ++++++----- webpack.config.ts | 19 +++++++-- 5 files changed, 110 insertions(+), 62 deletions(-) diff --git a/file.ts b/file.ts index 09fa7b00..0a59cbfa 100644 --- a/file.ts +++ b/file.ts @@ -753,8 +753,15 @@ namespace watcher { const data = buffer.toString(); if(this.verbose) { - for(const line of data.split("\n")) + const lines = data.split("\n"); + for(let index = 0; index < lines.length; index++) { + let line = lines[index]; + if(line.charAt(0) === "\r") + line = line.substr(1); + if(line === "" && index + 1 === lines.length) + break; console.log("%s: %s", this.name, line); + } } } @@ -783,20 +790,31 @@ namespace watcher { } protected start_command(): string[] { - return ["npm", "run", "ttsc", "--", "-w"]; + return ["npm", "run", "tsc", "--", "-w"]; } } export class SASSWatcher extends Watcher { constructor() { super("SASS Watcher"); - this.verbose = true; + this.verbose = false; } protected start_command(): string[] { return ["npm", "run", "sass", "--", "--watch", ".:."]; } } + + export class WebPackWatcher extends Watcher { + constructor() { + super("WebPack Watcher"); + this.verbose = true; + } + + protected start_command(): string[] { + return ["npm", "run", "watch-web"]; + } + } } function php_exe() : string { @@ -836,33 +854,48 @@ async function main_develop(node: boolean, target: "client" | "web", port: numbe if(flags.indexOf("--no-sass") == -1) await sasswatcher.start(); - try { - await server.launch(target === "client" ? CLIENT_APP_FILE_LIST : WEB_APP_FILE_LIST, { - port: port, - php: php_exe(), - search_options: { - source_path: __dirname, - parameter: [], - target: target, - mode: "dev", - serving: true - } - }); - } catch(error) { - console.error("Failed to start server: %o", error instanceof Error ? error.message : error); - return; - } - - console.log("Server started on %d", port); - console.log("To stop the session press ^K^C."); - - await new Promise(resolve => process.once('SIGINT', resolve)); - console.log("Stopping session."); + const webpackwatcher = new watcher.WebPackWatcher(); try { - await server.shutdown(); - } catch(error) { - console.warn("Failed to stop web server: %o", error instanceof Error ? error.message : error); + if(flags.indexOf("--no-webpack") == -1) + await webpackwatcher.start(); + + try { + await server.launch(target === "client" ? CLIENT_APP_FILE_LIST : WEB_APP_FILE_LIST, { + port: port, + php: php_exe(), + search_options: { + source_path: __dirname, + parameter: [], + target: target, + mode: "dev", + serving: true + } + }); + } catch(error) { + console.error("Failed to start server: %o", error instanceof Error ? error.message : error); + return; + } + + console.log("Server started on %d", port); + console.log("To stop the session press ^K^C."); + + await new Promise(resolve => process.once('SIGINT', resolve)); + console.log("Stopping session."); + + try { + await server.shutdown(); + } catch(error) { + console.warn("Failed to stop web server: %o", error instanceof Error ? error.message : error); + } + } catch (error) { + console.error("Failed to start WebPack watcher: %o", error instanceof Error ? error.message : error); + } finally { + try { + await webpackwatcher.stop(); + } catch(error) { + console.warn("Failed to stop WebPack watcher: %o", error instanceof Error ? error.message : error); + } } } catch(error) { console.error("Failed to start SASS watcher: %o", error instanceof Error ? error.message : error); diff --git a/package.json b/package.json index a0367b09..2192db96 100644 --- a/package.json +++ b/package.json @@ -7,17 +7,19 @@ "scripts": { "compile-sass": "sass --update shared/css/:shared/css/ web/css/:web/css/ client/css/:client/css/ vendor/:vendor/", "compile-project-base": "tsc -p tsbaseconfig.json", + "dtsgen": "node tools/dtsgen/index.js", "trgen": "node tools/trgen/index.js", "sass": "sass", - "csso": "csso", - "rebuild-structure-web-dev": "php files.php generate web dev", - "minify-web-rel-file": "terser --compress --mangle --ecma 6 --keep_classnames --keep_fnames --output", - "start": "npm run compile-file-helper && node file.js ndevelop", + "tsc": "tsc", + + "start": "npm run compile-project-base && node file.js ndevelop", + "build-web": "webpack --config webpack-web.config.js", "watch-web": "webpack --watch --config webpack-web.config.js", "build-client": "webpack --config webpack-client.config.js", "watch-client": "webpack --watch --config webpack-client.config.js", + "generate-i18n-gtranslate": "node shared/generate_i18n_gtranslate.js" }, "author": "TeaSpeak (WolverinDEV)", diff --git a/webpack-client.config.ts b/webpack-client.config.ts index 4866bbcf..3caac43e 100644 --- a/webpack-client.config.ts +++ b/webpack-client.config.ts @@ -1,21 +1,22 @@ import * as path from "path"; import * as config_base from "./webpack.config"; -const config = config_base.config("client"); -Object.assign(config.entry, { - "client-app": "./client/js/index.ts" -}); +export = () => config_base.config("client").then(config => { + Object.assign(config.entry, { + "client-app": "./client/js/index.ts" + }); -Object.assign(config.resolve.alias, { - "tc-shared": path.resolve(__dirname, "shared/js"), - /* backend hasn't declared but its available via "require()" */ - "tc-backend": path.resolve(__dirname, "shared/backend.d"), -}); + Object.assign(config.resolve.alias, { + "tc-shared": path.resolve(__dirname, "shared/js"), + /* backend hasn't declared but its available via "require()" */ + "tc-backend": path.resolve(__dirname, "shared/backend.d"), + }); -config.externals.push((context, request: string, callback) => { - if (request.startsWith("tc-backend/")) - return callback(null, `window["backend-loader"].require("${request}")`); - callback(); -}); + config.externals.push((context, request: string, callback) => { + if (request.startsWith("tc-backend/")) + return callback(null, `window["backend-loader"].require("${request}")`); + callback(); + }); -export = config; \ No newline at end of file + return Promise.resolve(config); +}); \ No newline at end of file diff --git a/webpack-web.config.ts b/webpack-web.config.ts index 23c50627..acc024a4 100644 --- a/webpack-web.config.ts +++ b/webpack-web.config.ts @@ -1,16 +1,17 @@ import * as path from "path"; import * as config_base from "./webpack.config"; -const config = config_base.config("web"); -Object.assign(config.entry, { - "shared-app": "./web/js/index.ts" -}); +export = () => config_base.config("web").then(config => { + Object.assign(config.entry, { + "shared-app": "./web/js/index.ts" + }); -Object.assign(config.resolve.alias, { - "tc-shared": path.resolve(__dirname, "shared/js"), - "tc-backend/web": path.resolve(__dirname, "web/js"), - "tc-backend": path.resolve(__dirname, "web/js"), - "tc-generated/codec/opus": path.resolve(__dirname, "web/native-codec/generated/TeaWeb-Worker-Codec-Opus.js"), -}); + Object.assign(config.resolve.alias, { + "tc-shared": path.resolve(__dirname, "shared/js"), + "tc-backend/web": path.resolve(__dirname, "web/js"), + "tc-backend": path.resolve(__dirname, "web/js"), + "tc-generated/codec/opus": path.resolve(__dirname, "web/native-codec/generated/TeaWeb-Worker-Codec-Opus.js"), + }); -export = config; \ No newline at end of file + return Promise.resolve(config); +}); \ No newline at end of file diff --git a/webpack.config.ts b/webpack.config.ts index 4416117c..5fdd49c1 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -1,6 +1,8 @@ import * as ts from "typescript"; import * as fs from "fs"; import trtransformer from "./tools/trgen/ts_transformer"; +import {exec} from "child_process"; +import * as util from "util"; const path = require('path'); const webpack = require("webpack"); @@ -13,7 +15,7 @@ const { CleanWebpackPlugin } = require('clean-webpack-plugin'); export let isDevelopment = process.env.NODE_ENV === 'development'; console.log("Webpacking for %s (%s)", isDevelopment ? "development" : "production", process.env.NODE_ENV || "NODE_ENV not specified"); -const generate_definitions = (target: string) => { +const generate_definitions = async (target: string) => { const git_rev = fs.readFileSync(path.join(__dirname, ".git", "HEAD")).toString(); let version; if(git_rev.indexOf("/") === -1) @@ -21,18 +23,27 @@ const generate_definitions = (target: string) => { else version = fs.readFileSync(path.join(__dirname, ".git", git_rev.substr(5).trim())).toString().substr(0, 7); + let timestamp; + try { + const { stdout } = await util.promisify(exec)("git show -s --format=%ct"); + timestamp = parseInt(stdout.toString()); + if(isNaN(timestamp)) throw "failed to parse timestamp '" + stdout.toString() + "'"; + } catch (error) { + console.error("Failed to get commit timestamp: %o", error); + throw "failed to get commit timestamp"; + } return { "__build": { target: JSON.stringify(target), mode: JSON.stringify(isDevelopment ? "debug" : "release"), version: JSON.stringify(version), - timestamp: Date.now(), + timestamp: timestamp, entry_chunk_name: JSON.stringify(target === "web" ? "shared-app" : "client-app") } as BuildDefinitions } as any; }; -export const config = (target: "web" | "client") => { return { +export const config = async (target: "web" | "client") => { return { entry: { "loader": "./loader/app/index.ts" }, @@ -63,7 +74,7 @@ export const config = (target: "web" | "client") => { return { minSize: 1024 * 8, maxSize: 1024 * 128 }), - new webpack.DefinePlugin(generate_definitions(target)) + new webpack.DefinePlugin(await generate_definitions(target)) ].filter(e => !!e), module: { rules: [