diff --git a/.gitignore b/.gitignore index 8dce8df8..1d400eb3 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ node_modules/ # Some build output /dist/ +/dist-package/ /declarations/ /travis-build/ diff --git a/ChangeLog.md b/ChangeLog.md index a68ba5dc..5772de8f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,9 @@ # Changelog: +* **17.03.21** + - Updated from webpack 4 to webpack 5 + - Reworked the client build process + - Using webpack dev server from now on + * **14.03.21** - Enchanted the bookmark system - Added support for auto connect on startup diff --git a/loader/app/maifest.ts b/loader/app/maifest.ts index 6462ce16..79c3da87 100644 --- a/loader/app/maifest.ts +++ b/loader/app/maifest.ts @@ -31,7 +31,7 @@ export async function loadManifest() : Promise { } try { - const response = await fetch(config.baseUrl + "js/manifest.json?_date=" + Date.now()); + const response = await fetch(config.baseUrl + "/manifest.json?_date=" + Date.now()); if(!response.ok) throw response.status + " " + response.statusText; manifest = await response.json(); @@ -56,7 +56,7 @@ export async function loadManifestTarget(chunkName: string, taskId: number) { modules: manifest.chunks[chunkName].modules }); - loader.style.load_multiple(manifest.chunks[chunkName].css_files.map(e => "js/" + e.file), { + loader.style.load_multiple(manifest.chunks[chunkName].css_files.map(e => e.file), { cache_tag: undefined, max_parallel_requests: 4 }, (entry, state) => { @@ -67,7 +67,7 @@ export async function loadManifestTarget(chunkName: string, taskId: number) { loader.setCurrentTaskName(taskId, script_name(entry, false)); }); - await loader.scripts.load_multiple(manifest.chunks[chunkName].files.map(e => "js/" + e.file), { + await loader.scripts.load_multiple(manifest.chunks[chunkName].files.map(e => e.file), { cache_tag: undefined, max_parallel_requests: 4 }, (script, state) => { diff --git a/package-lock.json b/package-lock.json index 6420ed43..d2a6b819 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3700,6 +3700,12 @@ "node-releases": "^1.1.58" } }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, "buffer-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", @@ -19518,11 +19524,29 @@ "camelcase": "^3.0.0" } }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3" + } + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "zip-webpack-plugin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/zip-webpack-plugin/-/zip-webpack-plugin-4.0.1.tgz", + "integrity": "sha512-G041Q4qUaog44Ynit6gs4o+o3JIv0WWfOLvc8Q3IxvPfuqd2KBHhpJWAXUB9Cm1JcWHTIOp9vS3oGMWa1p1Ehw==", + "dev": true, + "requires": { + "yazl": "^2.5.1" + } } } } diff --git a/package.json b/package.json index 6780b470..d146d363 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,8 @@ "webpack-bundle-analyzer": "^3.6.1", "webpack-cli": "^4.5.0", "webpack-dev-server": "^3.11.2", - "webpack-svg-sprite-generator": "^5.0.2" + "webpack-svg-sprite-generator": "^5.0.2", + "zip-webpack-plugin": "^4.0.1" }, "repository": { "type": "git", diff --git a/scripts/build.sh b/scripts/build.sh index e004bab2..cb4ebf5e 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -49,32 +49,18 @@ if [[ $_exit_code -ne 0 ]]; then exit 1 fi -echo "Generating style files" -npm run compile-scss; _exit_code=$? -if [[ $_exit_code -ne 0 ]]; then - echo "Failed to generate style files" - exit 1 -fi - if [[ "$build_type" == "release" ]]; then # Compile everything for release mode - NODE_ENV=production npm run build-$build_target; _exit_code=$? + NODE_ENV=production npm run build-$build_target -- --env package=1; _exit_code=$? if [[ $_exit_code -ne 0 ]]; then - echo "Failed to build the $build_target applcation" + echo "Failed to build the $build_target application" exit 1 fi elif [[ "$build_type" == "development" ]]; then - NODE_ENV=development npm run build-$build_target; _exit_code=$? + NODE_ENV=development npm run build-$build_target -- --env package=1; _exit_code=$? if [[ $_exit_code -ne 0 ]]; then - echo "Failed to build the $build_target applcation" + echo "Failed to build the $build_target application" exit 1 fi fi -echo "Generating environment" -node file.js generate $build_target ${build_type}; _exit_code=$? -if [[ $_exit_code -ne 0 ]]; then - echo "Failed to generate environment" - exit 1 -fi - -echo "$build_target builded successfully!" \ No newline at end of file +echo "$build_target build successfully!" \ No newline at end of file diff --git a/scripts/cleanup.sh b/scripts/cleanup.sh index 3ef26a0b..67ace0ae 100644 --- a/scripts/cleanup.sh +++ b/scripts/cleanup.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash BASEDIR=$(dirname "$0") -cd "$BASEDIR/../" +cd "$BASEDIR/../" || exit # This script cleanups all generated files function remove_if_exists() { diff --git a/scripts/git_index.sh b/scripts/git_index.sh index 6dc166df..acf8807e 100644 --- a/scripts/git_index.sh +++ b/scripts/git_index.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -response=$(git diff-index HEAD -- . ':!asm/libraries/' ':!package-lock.json' ':!vendor/') +response=$(git diff-index HEAD -- . ':!package-lock.json' ':!vendor/') if [[ "$response" != "" ]]; then if [[ "$1" == "sort-tag" ]]; then echo "0000000" diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index 7c5b2e00..0095640a 100644 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -34,52 +34,5 @@ install_node() { fi } -install_rust() { - rustup_version=$(rustup --version 2>/dev/null) - if [[ $? -ne 0 ]]; then - echo "> Missing rustup, installing..." - curl https://build.travis-ci.org/files/rustup-init.sh -sSf | sh -s -- -y --default-toolchain nightly - # shellcheck disable=SC2181 - [[ $? -ne 0 ]] && { - echo "> Failed to install rustup" - exit 1 - } - - PATH="$PATH:$HOME/.cargo/bin" - rustup_version=$(rustup --version 2>/dev/null) - echo "> Installed $rustup_version" - else - echo "> Found $rustup_version" - fi - - echo "> Installing/updating the wasm32-unknown-unknown host" - rustup target add wasm32-unknown-unknown - if [[ $? -ne 0 ]]; then - echo "> Failed to install/updating the wasm target" - exit 1 - fi -} - -install_wasmpack() { - wasmpack_version=$(wasm-pack --version 2>/dev/null) - if [[ $? -ne 0 ]]; then - echo "> Missing wasm-pack, installing..." - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - - # shellcheck disable=SC2181 - [[ $? -ne 0 ]] && { - echo "> Failed to install wasm-pack" - exit 1 - } - - wasmpack_version=$(wasm-pack --version 2>/dev/null) - echo "> Installed $wasmpack_version" - else - echo "> Found $wasmpack_version" - fi -} - install_sys_deps -install_node -install_rust -install_wasmpack \ No newline at end of file +install_node \ No newline at end of file diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index 05a5d62a..67369ad7 100644 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -176,11 +176,6 @@ function execute_build_release() { "Failed to build release" \ "./scripts/build.sh web release" - execute \ - "Packaging release" \ - "Failed to package release" \ - "./scripts/web_package.sh release" - move_target_file } function execute_build_debug() { @@ -189,11 +184,6 @@ function execute_build_debug() { "Failed to build debug" \ "./scripts/build.sh web dev" - execute \ - "Packaging release" \ - "Failed to package debug" \ - "./scripts/web_package.sh dev" - move_target_file } diff --git a/scripts/travis/deploy_github.sh b/scripts/travis/deploy_github.sh index 945f9b18..5ce55296 100644 --- a/scripts/travis/deploy_github.sh +++ b/scripts/travis/deploy_github.sh @@ -86,10 +86,10 @@ for folder in "${folders[@]}"; do [[ $? -eq 0 ]] && { echo " Uploaded."; - uploaded_files+="$file" + uploaded_files+=("$file") } || { echo "Failed to generate git release" - failed_files+="$file" + failed_files+=("$file") } done done diff --git a/scripts/travis/deploy_server.sh b/scripts/travis/deploy_server.sh index 7732106b..b3a1c3a9 100644 --- a/scripts/travis/deploy_server.sh +++ b/scripts/travis/deploy_server.sh @@ -37,7 +37,7 @@ _exit_code=$? echo "Failed to delete the old .zip files ($_exit_code)" } -filename="TeaWeb-Release-$(git rev-parse --short HEAD).zip" +filename="TeaWeb-release-$(git rev-parse --short HEAD).zip" sftp -oStrictHostKeyChecking=no -oIdentitiesOnly=yes -i /tmp/sftp_key TeaSpeak-Travis-Web@web.teaspeak.dev << EOF put $file tmp-upload/$filename EOF diff --git a/scripts/web_package.sh b/scripts/web_package.sh deleted file mode 100644 index 00937363..00000000 --- a/scripts/web_package.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash - -cd "$(dirname "$0")/../" || { echo "Failed to enter base directory"; exit 1; } - -if [[ "$1" == "development" ]] || [[ "$1" == "dev" ]] || [[ "$1" == "dev" ]]; then - source_path="web/environment/development" - type="development" -elif [[ "$1" == "release" ]] || [[ "$1" == "rel" ]]; then - source_path="web/environment/release" - type="release" -else - if [[ $# -lt 1 ]]; then - echo "Invalid argument count!" - else - echo "Invalid option $1" - fi - echo 'Available options are: "development" or "dev", "release" or "rel"' - exit 1 -fi - -if [[ ! -d "$source_path" ]]; then - echo "Could not find environment! ($source_path)" - echo "Please generate it first!" - exit 1 -fi - -response=$(git diff-index HEAD -- . ':!asm/libraries/' ':!package-lock.json' ':!vendor/') -if [[ "$response" != "" ]]; then - echo "You're using a private modified build! Cant assign git hash!" - NAME="TeaWeb-${type}.zip" -else - NAME="TeaWeb-${type}-$(git rev-parse --short HEAD).zip" -fi - -if [[ -e ${NAME} ]]; then - echo "Found old file. Deleting it." - rm -r "${NAME}" -fi - -current_path=$(pwd) -cd "$source_path" || { echo "Failed to enter source path"; exit 1; } - -zip -9 -r "${NAME}" ./*; _exit_code=$? -if [[ $_exit_code -ne 0 ]]; then - echo "Failed to package environment!" - exit 1 -fi - -cd "$current_path" || { echo "Failed to reenter source path"; exit 1; } - -mv "${source_path}/${NAME}" . -echo "Release package successfully packaged!" -echo "Target file: ${NAME} ($(pwd))" \ No newline at end of file diff --git a/shared/img/music/empty_disk.svg b/shared/img/music/empty_disk.svg deleted file mode 100644 index 78c4bdaf..00000000 --- a/shared/img/music/empty_disk.svg +++ /dev/null @@ -1 +0,0 @@ -image/svg+xml diff --git a/shared/img/music/icon_music_pause.svg b/shared/img/music/icon_music_pause.svg deleted file mode 100644 index ccf1b24f..00000000 --- a/shared/img/music/icon_music_pause.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/shared/img/music/settings.svg b/shared/img/music/settings.svg deleted file mode 100644 index e40035ce..00000000 --- a/shared/img/music/settings.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/shared/img/music/no-thumbnail.png b/shared/js/ui/frames/side/MusicPlaylistNoThumbnail.png similarity index 100% rename from shared/img/music/no-thumbnail.png rename to shared/js/ui/frames/side/MusicPlaylistNoThumbnail.png diff --git a/shared/js/ui/frames/side/MusicPlaylistRenderer.tsx b/shared/js/ui/frames/side/MusicPlaylistRenderer.tsx index 7594297a..acfb2907 100644 --- a/shared/js/ui/frames/side/MusicPlaylistRenderer.tsx +++ b/shared/js/ui/frames/side/MusicPlaylistRenderer.tsx @@ -13,6 +13,7 @@ import {preview_image} from "tc-shared/ui/frames/image_preview"; import {joinClassList, useTr} from "tc-shared/ui/react-elements/Helper"; import {spawnContextMenu} from "tc-shared/ui/ContextMenu"; import {copyToClipboard} from "tc-shared/utils/helpers"; +import ImagePlaylistNoThumbnail from "./MusicPlaylistNoThumbnail.png"; const cssStyle = require("./MusicPlaylistRenderer.scss"); @@ -58,7 +59,7 @@ export const DefaultThumbnail = (_props: { type: "loading" | "none-present" }) = return ( {useTr("loading")} ); diff --git a/tools/trgen/WebpackPlugin.ts b/tools/trgen/WebpackPlugin.ts index 6f1a41f9..f2d64142 100644 --- a/tools/trgen/WebpackPlugin.ts +++ b/tools/trgen/WebpackPlugin.ts @@ -1,14 +1,13 @@ import * as ts from "typescript"; -import {createTransformer, deltaTranslations, TransformerConfig} from "./TsTransformer"; +import {createTransformer, TransformerConfig} from "./TsTransformer"; import * as webpack from "webpack"; -import {extractJsRendererTranslations} from "./JsRendererGenerator"; import * as path from "path"; export interface TranslateableWebpackPluginConfig { assetName: string, } -export class TranslateableWebpackPlugin { +export default class TranslateableWebpackPlugin { private readonly config: TranslateableWebpackPluginConfig; private readonly transformerConfig: TransformerConfig; diff --git a/webpack-client.config.ts b/webpack-client.config.ts index 04be2197..50e35af6 100644 --- a/webpack-client.config.ts +++ b/webpack-client.config.ts @@ -1,7 +1,7 @@ import * as path from "path"; import * as config_base from "./webpack.config"; -export = () => config_base.config("client").then(config => { +export = env => config_base.config(env, "client").then(config => { Object.assign(config.entry, { "client-app": ["./client/app/index.ts"] }); diff --git a/webpack-web.config.ts b/webpack-web.config.ts index 757886c6..e9f46390 100644 --- a/webpack-web.config.ts +++ b/webpack-web.config.ts @@ -1,7 +1,7 @@ import * as path from "path"; import * as config_base from "./webpack.config"; -export = () => config_base.config("web").then(config => { +export = env => config_base.config(env, "web").then(config => { Object.assign(config.entry, { "shared-app": ["./web/app/index.ts"], "modal-external": ["./web/app/index-external.ts"] diff --git a/webpack.config.ts b/webpack.config.ts index 24731046..567f7070 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -3,18 +3,21 @@ import * as util from "util"; import * as path from "path"; import * as child_process from "child_process"; +import {GeneratedAssetPlugin} from "./webpack/GeneratedAssetPlugin"; + import { DefinePlugin, Configuration, } from "webpack"; import { Plugin as SvgSpriteGenerator } from "webpack-svg-sprite-generator"; -const ManifestGenerator = require("./webpack/ManifestPlugin"); -const HtmlWebpackInlineSourcePlugin = require("./webpack/HtmlWebpackInlineSource"); +import ManifestGenerator from "./webpack/ManifestPlugin"; +import HtmlWebpackInlineSourcePlugin from "./webpack/HtmlWebpackInlineSource"; +import TranslateableWebpackPlugin from "./tools/trgen/WebpackPlugin"; +import ZipWebpackPlugin from "zip-webpack-plugin"; import HtmlWebpackPlugin from "html-webpack-plugin"; -import {TranslateableWebpackPlugin} from "./tools/trgen/WebpackPlugin"; -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); -const TerserPlugin = require('terser-webpack-plugin'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); +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"; const { CleanWebpackPlugin } = require("clean-webpack-plugin"); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); @@ -22,33 +25,57 @@ const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); 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 generateDefinitions = async (target: string) => { - const gitRevision = fs.readFileSync(path.join(__dirname, ".git", "HEAD")).toString(); - let version; - if(gitRevision.indexOf("/") === -1) { - version = (gitRevision || "0000000").substr(0, 7); - } else { - version = fs.readFileSync(path.join(__dirname, ".git", gitRevision.substr(5).trim())).toString().substr(0, 7); - } +interface LocalBuildInfo { + target: "client" | "web", + mode: "debug" | "release", - let timestamp; - try { - const { stdout } = await util.promisify(child_process.exec)("git show -s --format=%ct"); - timestamp = parseInt(stdout.toString()); - if(isNaN(timestamp)) { - throw "failed to parse timestamp '" + stdout.toString() + "'"; + gitVersion: string, + gitTimestamp: number, + + unixTimestamp: number, + localTimestamp: string +} + +let localBuildInfo: LocalBuildInfo; +const generateLocalBuildInfo = async (target: string): Promise => { + let info: LocalBuildInfo = {} as any; + + info.target = target as any; + info.mode = isDevelopment ? "debug" : "release"; + + { + const gitRevision = fs.readFileSync(path.join(__dirname, ".git", "HEAD")).toString(); + if(gitRevision.indexOf("/") === -1) { + info.gitVersion = (gitRevision || "0000000").substr(0, 7); + } else { + info.gitVersion = fs.readFileSync(path.join(__dirname, ".git", gitRevision.substr(5).trim())).toString().substr(0, 7); + } + + 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"; } - } catch (error) { - console.error("Failed to get commit timestamp: %o", error); - throw "failed to get commit timestamp"; } + info.unixTimestamp = Date.now(); + info.localTimestamp = new Date().toString(); + + return info; +}; + +const generateDefinitions = async (target: string) => { return { "__build": { target: JSON.stringify(target), mode: JSON.stringify(isDevelopment ? "debug" : "release"), - version: JSON.stringify(version), - timestamp: timestamp, + version: JSON.stringify(localBuildInfo.gitVersion), + timestamp: localBuildInfo.gitTimestamp, entry_chunk_name: JSON.stringify(target === "web" ? "shared-app" : "client-app") } as BuildDefinitions } as any; @@ -83,7 +110,9 @@ const generateIndexPlugin = (target: "web" | "client"): HtmlWebpackPlugin => { return new HtmlWebpackPlugin(options); } -export const config = async (target: "web" | "client"): Promise => { +export const config = async (env: any, target: "web" | "client"): Promise => { + localBuildInfo = await generateLocalBuildInfo(target); + const translateablePlugin = new TranslateableWebpackPlugin({ assetName: "translations.json" }); return { @@ -97,7 +126,20 @@ export const config = async (target: "web" | "client"): Promise !!e), module: { diff --git a/webpack/GeneratedAssetPlugin.ts b/webpack/GeneratedAssetPlugin.ts new file mode 100644 index 00000000..50c2ddcc --- /dev/null +++ b/webpack/GeneratedAssetPlugin.ts @@ -0,0 +1,43 @@ +import * as webpack from "webpack"; +import {Compilation} from "webpack"; + +export interface GeneratedAsset { + assetName: string, + content: string | (() => string) +} + +export interface GeneratedAssetPluginConfig { + customFiles: GeneratedAsset[] +} + +export class GeneratedAssetPlugin { + readonly options: GeneratedAssetPluginConfig; + + constructor(options: GeneratedAssetPluginConfig) { + this.options = options; + } + + apply(compiler: webpack.Compiler) { + compiler.hooks.thisCompilation.tap({ + name: "GeneratedAssetPlugin", + stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL + }, compilation => { + compilation.hooks.processAssets.tap("GeneratedAssetPlugin", () => { + for(const asset of this.options.customFiles) { + let content: string; + if(typeof asset.content === "string") { + content = asset.content; + } else { + content = asset.content(); + } + + compilation.emitAsset(asset.assetName, new webpack.sources.RawSource(content), { + immutable: true, + hotModuleReplacement: true, + size: content.length + }); + } + }); + }); + } +} \ No newline at end of file diff --git a/webpack/HtmlWebpackInlineSource.ts b/webpack/HtmlWebpackInlineSource.ts index d25c705f..621d6013 100644 --- a/webpack/HtmlWebpackInlineSource.ts +++ b/webpack/HtmlWebpackInlineSource.ts @@ -135,4 +135,4 @@ function getAssetByName (assests, assetName) { } } -module.exports = HtmlWebpackInlineSourcePlugin; \ No newline at end of file +export = HtmlWebpackInlineSourcePlugin; \ No newline at end of file