diff --git a/.github/workflows/ci-mmsd-demo.yml b/.github/workflows/ci-mmsd-demo.yml index 49965e9..5153624 100644 --- a/.github/workflows/ci-mmsd-demo.yml +++ b/.github/workflows/ci-mmsd-demo.yml @@ -3,10 +3,7 @@ name: CI build mmsd-demo on: push: branches: - - master - - develop - schedule: - - cron: '0 2 * * *' + - mmsd-demo repository_dispatch: types: [ uxkit-mmsd-demo ] diff --git a/frontend/electron-builder.yml b/frontend/electron-builder.yml index 9e61dad..5e58ca5 100644 --- a/frontend/electron-builder.yml +++ b/frontend/electron-builder.yml @@ -1,19 +1,23 @@ -appId: io.voxeet.app -productName: Voxeet +appId: io.dolby.app +productName: Dolby.io buildVersion: local extends: null electronVersion: 9.2.0 +artifactName: ${productName}-${version}.${ext} extraMetadata: description: DesktopSDK_0bb26b73_v9.2.0 files: + - dist/*.png + - dist/*.ico - dist/*.svg - dist/*.ttf - dist/sounds/*.mp3 - dist/index.html - dist/bundle.js - dist/images + - dist/fonts - src/main.js - src/preload.js - node_modules/ @@ -50,10 +54,11 @@ mac: win: target: nsis - icon: dist/icon.png + icon: dist/favicon.ico certificateFile: /Users/dolbyvoice/cert_win/code_signing.pfx certificatePassword: '' squirrelWindows: + artifactName: ${productName}-${version}.${ext} iconUrl: >- https://raw.githubusercontent.com/voxeet/voxeet-io-web/master/public/icon.png diff --git a/frontend/package.json b/frontend/package.json index 52b1640..5cfc804 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,13 +1,14 @@ { - "name": "voxeet-io", - "version": "1.0.0-beta.1", + "name": "dolby-io", + "description": "Dolby Interactivity API Desktop Showcase App", + "version": "1.0.0-beta.2", "private": true, "main": "src/main.js", "scripts": { "dist": "npm run build:electron && ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES=true build", "bootstrap": "yarn link @voxeet/voxeet-web-sdk && yarn link @voxeet/media-engine && yarn link @voxeet/react-components", - "start": "webpack-dev-server -d --hot --inline --content-base", - "build": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js --progress -p", + "start": "webpack serve --hot --inline", + "build": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js --progress", "get-version": "cross-env-shell echo ${npm_package_version}", "builde": "cross-env webpack --config webpack.config.electron.js --progress", "builde:prod": "cross-env DEBUG=true NODE_ENV=production yarn builde", @@ -16,12 +17,12 @@ "builde:bin": "cross-env yarn run electron-builder -c.electronDist=${NDS_RUNTIME:-../../NDS} -c.buildVersion=${CI_PIPELINE_ID:-local} --publish=never", "builde:bin:osx": "yarn builde:bin -- --macos --x64", "builde:bin:win": "yarn builde:bin -- --windows --x64", - "builde:prod:bin:osx": "yarn builde:bin:osx -- '-c.productName=Voxeet'", - "builde:prod:bin:win": "yarn builde:bin:win -- '-c.productName=Voxeet'", - "builde:staging:bin:osx": "yarn builde:bin:osx -- '-c.productName=Voxeet(staging)'", - "builde:staging:bin:win": "yarn builde:bin:win -- '-c.productName=Voxeet(staging)'", - "builde:dev-staging:bin:osx": "yarn builde:bin:osx -- '-c.productName=Voxeet(dev-staging)'", - "builde:dev-staging:bin:win": "yarn builde:bin:win -- '-c.productName=Voxeet(dev-staging)'" + "builde:prod:bin:osx": "yarn builde:bin:osx -- '-c.productName=dolby-io'", + "builde:prod:bin:win": "yarn builde:bin:win -- '-c.productName=dolby-io'", + "builde:staging:bin:osx": "yarn builde:bin:osx -- '-c.productName=dolby-io(staging)'", + "builde:staging:bin:win": "yarn builde:bin:win -- '-c.productName=dolby-io(staging)'", + "builde:dev-staging:bin:osx": "yarn builde:bin:osx -- '-c.productName=dolby-io(dev-staging)'", + "builde:dev-staging:bin:win": "yarn builde:bin:win -- '-c.productName=dolby-io(dev-staging)'" }, "author": "Dolby", "contributors": [ @@ -32,50 +33,48 @@ "IE 11" ], "dependencies": { - "@babel/polyfill": "^7.8.7", - "@trodi/electron-splashscreen": "^0.3.4", - "@voxeet/react-components": "file:../../voxeet-uxkit-react/", - "@voxeet/voxeet-web-sdk": "file:../../voxeet-sdk/packages/voxeet-web-sdk", - "axios": "^0.19.2", - "browserslist": "^4.5.2", - "core-js": "2", + "@babel/polyfill": "^7.12.1", + "@trodi/electron-splashscreen": "^1.0.0", + "@voxeet/react-components": "^3.2.3", + "@voxeet/voxeet-web-sdk": "^3.3.0", + "about-window": "^1.14.0", + "axios": "^0.21.1", + "browserslist": "^4.16.6", + "core-js": "^3.15.2", "electron-window-state": "^5.0.3", - "express": "^4.0.0", - "react": "16.9.0", - "react-dom": "16.9.0", - "react-localization": "^1.0.14", - "react-redux": "7.1.1", - "react-router-dom": "5.0.1", - "redux": "4.0.4", - "redux-thunk": "2.3.0" + "express": "^4.17.1", + "prettier": "^2.3.2", + "react": "17.0.2", + "react-dom": "17.0.2", + "react-localization": "^1.0.17", + "react-redux": "^7.2.4", + "react-router-dom": "^5.2.0", + "redux-logger": "^3.0.6", + "redux-thunk": "^2.3.0" }, "resolutions": { - "react": "16.9.0", - "react-dom": "16.9.0" + "react": "17.0.2", + "react-dom": "17.0.2" }, "devDependencies": { - "@babel/core": "^7.3.4", - "@babel/preset-env": "^7.3.4", - "@babel/preset-react": "^7.0.0", - "babel-loader": "^8.0.5", - "copy-webpack-plugin": "^4.2.0", - "cross-env": "^7.0.2", - "css-loader": "^2.1.1", + "@babel/core": "^7.14.8", + "@babel/preset-env": "^7.14.8", + "@babel/preset-react": "^7.14.5", + "babel-loader": "^8.2.2", + "copy-webpack-plugin": "^9.0.1", + "cross-env": "^7.0.3", + "css-loader": "^6.2.0", "electron": "9.4.4", - "electron-builder": "^22.11.7", + "electron-builder": "^22.10.5", "electron-builder-squirrel-windows": "^22.10.5", - "extract-text-webpack-plugin": "^4.0.0-beta.0", - "file-loader": "^3.0.1", - "html-webpack-plugin": "^3.2.0", - "prettier": "^1.18.2", - "prettier-webpack-plugin": "^1.2.0", - "react-hot-loader": "^3.0.0-beta.7", - "style-loader": "^0.23.1", - "uglifyjs-webpack-plugin": "^1.1.5", - "url-loader": "^0.5.9", - "webpack": "^4.29.6", - "webpack-cli": "^3.2.0", - "webpack-dev-server": "^3.1.14" + "html-webpack-plugin": "^5.3.2", + "mini-css-extract-plugin": "^2.1.0", + "style-loader": "^3.2.1", + "terser-webpack-plugin": "^5.1.4", + "url-loader": "^4.1.1", + "webpack": "^5.45.1", + "webpack-cli": "^4.7.2", + "webpack-dev-server": "^3.11.2" }, "peerDependencies": { "express": "^4.0.0" @@ -83,6 +82,8 @@ "files": [ "../README.md", "dist/", - "src/preload.js" + "src/preload.js", + "public/icon.png", + "public/favicon.ico" ] } diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico index ebb401d..df17535 100644 Binary files a/frontend/public/favicon.ico and b/frontend/public/favicon.ico differ diff --git a/frontend/public/icon.png b/frontend/public/icon.png index 31f66f5..c5316c4 100644 Binary files a/frontend/public/icon.png and b/frontend/public/icon.png differ diff --git a/frontend/public/index.html b/frontend/public/index.html index 49cbfcc..8e8fdc0 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -10,7 +10,7 @@ - Dolby.io + Dolby Interactivity API Desktop Showcase App diff --git a/frontend/src/app/App.js b/frontend/src/app/App.js index f89a9d8..1e6edbe 100644 --- a/frontend/src/app/App.js +++ b/frontend/src/app/App.js @@ -71,15 +71,14 @@ class App extends Component { }; this.handleClick = this.handleClick.bind(this); this.handleChangeUserName = this.handleChangeUserName.bind(this); - this.handleChangeConferenceName = this.handleChangeConferenceName.bind( - this - ); + this.handleChangeConferenceName = this.handleChangeConferenceName.bind(this); this.escFunction = this.escFunction.bind(this); this.toggleChangeListener = this.toggleChangeListener.bind(this); this.toggleWidgetMode = this.toggleWidgetMode.bind(this); this.toggleSimulcastMode = this.toggleSimulcastMode.bind(this); this.toggleDolbyVoice = this.toggleDolbyVoice.bind(this); this.toggleConfiguration = this.toggleConfiguration.bind(this); + this.title = document.title; } componentDidMount() { @@ -147,6 +146,10 @@ class App extends Component { /*ReactDOM.unmountComponentAtNode(document.getElementById('voxeet-widget')); const oldConferenceName = this.state.conferenceName*/ this.setState({ isSubmit: false, isDemo: false }); + document.title=`${this.title}`; + if(this.props.handleLeave) { + this.props.handleLeave(); + } /*this.props.history.push('/') window.location.reload()*/ } @@ -176,6 +179,7 @@ class App extends Component { } handleClick() { + document.title=`${this.title} - ${this.state.conferenceName}`; this.props.history.push("/" + this.state.conferenceName); /*if (VoxeetSdk.isElectron) { // TODO: Check if possible to integrate into the SDK diff --git a/frontend/src/app/VoxeetConference.js b/frontend/src/app/VoxeetConference.js index 7559880..7502a38 100644 --- a/frontend/src/app/VoxeetConference.js +++ b/frontend/src/app/VoxeetConference.js @@ -1,21 +1,43 @@ import React, { Component } from "react"; -import "core-js/es6/"; import ReactDOM from "react-dom"; import PropTypes from "prop-types"; import thunkMidleware from "redux-thunk"; import { combineReducers, createStore, applyMiddleware } from "redux"; +import { Provider } from "react-redux"; import axios from "axios"; - import VoxeetSdk from "@voxeet/voxeet-web-sdk"; import { ConferenceRoom, VoxeetProvider, + getUxKitContext, + setUxKitContext, reducer as voxeetReducer } from "@voxeet/react-components"; +import "@voxeet/react-components/dist/voxeet-react-components.css"; -window.VoxeetSdk = VoxeetSdk; +// a naive example +const contextApp = React.createContext(); +const reducerApp = (state = {}, action) => { + switch (action.type) { + default: { + return state; + } + } +}; -import "@voxeet/react-components/dist/voxeet-react-components.css"; +const reducers = combineReducers({ + voxeet: voxeetReducer, +}); + +const middlewaresApp = [], middlewaresUxKit = []; +middlewaresApp.push(thunkMidleware); +middlewaresUxKit.push(thunkMidleware); +if (process.env.NODE_ENV === `development`) { + const { logger } = require(`redux-logger`); + + //middlewaresApp.push(logger); + //middlewaresApp.push(logger); +} const AUTH_SERVER = process.env.AUTH_SERVER || ""; const SESSION_SERVER = @@ -28,10 +50,10 @@ class VoxeetConference extends Component { .toLowerCase() .replace(/ /g, ""); const settings = { - conferenceAlias: conferenceName + conferenceAlias: conferenceName, }; const reducers = combineReducers({ - voxeet: voxeetReducer + voxeet: voxeetReducer, }); let name = this.props.userName; @@ -88,14 +110,16 @@ class VoxeetConference extends Component { const userInfo = { name: name, - avatarUrl: photoURL + avatarUrl: photoURL, }; var constraints = { audio: true, - video: true + video: true, }; - const configureStore = () => - createStore(reducers, applyMiddleware(thunkMidleware)); + const createStoreUxKit = () => + createStore(reducers, applyMiddleware(...middlewaresApp)); + const createStoreApp = () => + createStore(reducerApp, applyMiddleware(...middlewaresUxKit)); let displayModes = ["tiles", "speaker"]; if (this.props.isDemo && VoxeetSdk.isElectron) { displayModes = ["list", "tiles", "speaker"]; @@ -105,7 +129,7 @@ class VoxeetConference extends Component { let accessToken, refreshToken; const doRefreshToken = () => { - return axios.get(`${AUTH_SERVER}/api/token`, {}).then(response => { + return axios.get(`${AUTH_SERVER}/api/token`, {}).then((response) => { accessToken = response.data.access_token; refreshToken = response.data.refresh_token; @@ -117,45 +141,50 @@ class VoxeetConference extends Component { let token = ""; axios .get(`${AUTH_SERVER}/api/token`, {}) - .then(response => { + .then((response) => { //console.log("TOKEN: ", response); accessToken = response.data.access_token; refreshToken = response.data.refresh_token; ReactDOM.render( - - - , + + + {/**/} {/*Alternative to previous line*/} + + {/**/} + + , document.getElementById("voxeet-widget") ); }) - .catch(error => { + .catch((error) => { console.log(error); }); } catch (e) { @@ -186,7 +215,7 @@ VoxeetConference.propTypes = { VoxeetConference.defaultProps = { conferenceName: "conference_name", - userName: "Guest " + Math.floor(Math.random() * 100 + 1) + userName: "Guest " + Math.floor(Math.random() * 100 + 1), }; export default VoxeetConference; diff --git a/frontend/src/index.js b/frontend/src/index.js index ef15165..bd32588 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -3,3 +3,7 @@ import ReactDOM from "react-dom"; import Root from "./Root"; ReactDOM.render(, document.getElementById("root")); + +if (module && module.hot) { + module.hot.accept(); +} \ No newline at end of file diff --git a/frontend/src/main.js b/frontend/src/main.js index 9cc51c8..ad4ee00 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -3,6 +3,7 @@ const {app, BrowserWindow, Menu, ipcMain, powerSaveBlocker, systemPreferences, d const path = require('path'); const url = require('url'); const windowStateKeeper = require('electron-window-state'); +const openAboutWindow = require('about-window').default; let arguments = process.argv; @@ -37,7 +38,23 @@ if (process.platform === 'darwin') { const template = [{ label: "Application", submenu: [ - { label: "About Application", selector: "orderFrontStandardAboutPanel:" }, + //{label: "About Application", selector: "orderFrontStandardAboutPanel:"}, + { + label: "About Application", click: function () { + openAboutWindow({ + icon_path: path.join(__dirname, '..', 'dist', 'icon.png'), + adjust_window_size: true, + copyright: 'Copyright (c) 2021 Dolby', + product_name: 'Dolby.io', + description: 'Dolby Interactivity API Desktop Showcase App', + // package_json_dir: __dirname, + // use_version_info: [ + // ['my version entry 1', 'a.b.c'], + // ['my version entry 2', 'x.y.z'], + // ], + }); + } + }, { type: "separator" }, { label: "Quit", accelerator: "Command+Q", click: function() { app.quit(); }} ]}, { @@ -100,6 +117,7 @@ app.on('ready', async () => { y: mainWindowState.y, width: mainWindowState.width, height: mainWindowState.height, + title: app.getName(), webPreferences: { nodeIntegration: false, contextIsolation: true, @@ -108,13 +126,24 @@ app.on('ready', async () => { }); ipcMain.on('conferenceJoined', (e) => { - console.error('conference joined'); - //powerId = powerSaveBlocker.start("prevent-display-sleep"); CCS-1857 + // console.log('conference joined'); + try { + powerId = powerSaveBlocker.start("prevent-display-sleep"); //CCS-1857 + } catch(e) { + console.error('Could not start power save blocker', e.message); + } }); ipcMain.on('conferenceLeft', (e) => { - powerSaveBlocker.stop(powerId); + // console.log('conference left'); + try { + if (powerId !== null) { + powerSaveBlocker.stop(powerId); + } powerId = null; + } catch(e) { + console.error('Could not stop power save blocker', e.message); + } }); ipcMain.on('leave', (e) => { diff --git a/frontend/webpack.config.electron.common.js b/frontend/webpack.config.electron.common.js index 83b043d..3812f74 100644 --- a/frontend/webpack.config.electron.common.js +++ b/frontend/webpack.config.electron.common.js @@ -1,9 +1,9 @@ const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); -const ExtractTextPlugin = require("extract-text-webpack-plugin"); -var PrettierPlugin = require("prettier-webpack-plugin"); +const CopyPlugin = require("copy-webpack-plugin"); +const TerserPlugin = require("terser-webpack-plugin"); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); try { require("os").networkInterfaces(); @@ -30,76 +30,91 @@ module.exports = configuration => { rules: [ { test: /.js?$/, - loaders: ["babel-loader"], - include: path.resolve(__dirname) + use: ["babel-loader"], + include: path.resolve(__dirname), }, { test: /\.css$/, - loaders: ["style-loader", "css-loader"] + use: ["style-loader", "css-loader"], }, { - test: /.jsx?$/, - loaders: ["babel-loader"], - include: path.resolve(__dirname) + test: /.less$/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + 'less-loader' + ], }, { - test: /.less$/, - loader: "style-loader!css-loader!less-loader" + test: /.jsx?$/, + use: ["babel-loader"], + include: path.resolve(__dirname), }, { test: /\.mp3$/, - loader: "file-loader", - options: { - name: "sounds/[name].[ext]" - } + // use: "file-loader", + type: 'asset/resource', + generator: { + filename: "sounds/[name].[ext]", + }, }, { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/font-woff", - options: { - name: "fonts/[name].[ext]" - } + // use: "url-loader?limit=10000&mimetype=application/font-woff", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", + }, }, { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/font-woff", - options: { - name: "fonts/[name].[ext]" - } + // use: "url-loader?limit=10000&mimetype=application/font-woff", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", + }, }, { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/octet-stream", - options: { - name: "fonts/[name].[ext]" - } + // use: "url-loader?limit=10000&mimetype=application/octet-stream", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", + }, }, { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, - loader: "file-loader", - options: { - name: "fonts/[name].[ext]" - } + // use: "file-loader", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", + }, }, { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=image/svg+xml", - options: { - name: "images/[name].[ext]" - } + // use: "url-loader?limit=10000&mimetype=image/svg+xml", + type: 'asset/resource', + generator: { + filename: "images/[name][ext]", + }, }, { test: /\.(jpg|jpeg|gif|png)$/, - loader: "url-loader?limit=65000&name=images/[name].[ext]" + type: 'asset/resource', + generator: { + filename: "images/[name][ext]", + }, + // use: "url-loader?limit=65000&name=images/[name].[ext]", }, { test: /\.otf(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/octet-stream", - options: { - name: "fonts/[name].[ext]" - } - } - ] + // use: "url-loader?limit=10000&mimetype=application/octet-stream", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", + }, + }, + ], }, plugins: [ new webpack.DefinePlugin({ @@ -109,18 +124,22 @@ module.exports = configuration => { AUTH_SERVER: JSON.stringify(configuration.auth_server) } }), - new PrettierPlugin(), - new CopyWebpackPlugin([ - { from: "./src/static", ignore: ["*.html"] }, - "./public/favicon.ico", - "./public/icon.png", - "./public/manifest.json" - ]), + new CopyPlugin({ + patterns: [ + { from: "./public/favicon.ico"}, + { from: "./public/icon.png"}, + { from: "./src/static"}, + { from: "./node_modules/@voxeet/react-components/dist/fonts", to:'./fonts'}, + { from: "./node_modules/@voxeet/react-components/dist/images", to:'./images'}, + { from: "./node_modules/@voxeet/react-components/dist/sounds", to:'./sounds'}, + "./public/manifest.json", + ] + }), + new MiniCssExtractPlugin(), new HtmlWebpackPlugin({ - cache: false, - showErrors: true, + inject: true, template: "./public/index.html", - js: [] + js: [], }), new webpack.NoEmitOnErrorsPlugin() ] diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index d520653..52dca81 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -2,6 +2,7 @@ const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // Try the environment variable, otherwise use localhost const AUTH_SERVER = process.env.AUTH_SERVER || ''; @@ -15,17 +16,18 @@ try { module.exports = { entry: [ "@babel/polyfill", - "react-hot-loader/patch", "webpack/hot/only-dev-server", // "only" prevents reload on syntax errors "./src/index.js", ], + mode: 'development', devtool: "source-map", output: { path: path.join(__dirname, "dist"), - filename: "bundle.js", - publicPath: "", + chunkFilename: '[id].[chunkhash].js', + publicPath: "/", }, optimization: { + minimize: false, splitChunks: { // include all types of chunks chunks: 'all', @@ -39,97 +41,124 @@ module.exports = { disableHostCheck: true, host: "0.0.0.0", historyApiFallback: true, + hot: true, + writeToDisk: true, + watchOptions: { + poll: true, + }, }, module: { rules: [ { - test: /\.js$/, - loaders: ["babel-loader"], - exclude: /node_modules/, + test: /.js?$/, + use: ["babel-loader"], include: path.resolve(__dirname), }, { test: /\.css$/, - loaders: ["style-loader", "css-loader"], + use: ["style-loader", "css-loader"], }, { - test: /.jsx?$/, - loaders: ["babel-loader"], - exclude: /node_modules/, - include: path.resolve(__dirname), + test: /.less$/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + 'less-loader' + ], }, { - test: /.less$/, - loader: "style-loader!css-loader!less-loader", + test: /.jsx?$/, + use: ["babel-loader"], + include: path.resolve(__dirname), }, { test: /\.mp3$/, - loader: "file-loader", - options: { - name: "sounds/[name].[ext]", + // use: "file-loader", + type: 'asset/resource', + generator: { + filename: "sounds/[name].[ext]", }, }, { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/font-woff", - options: { - name: "fonts/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=application/font-woff", + type: 'asset/resource', + generator: { + filename: "fonts/[name].[ext]", }, }, { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/font-woff", - options: { - name: "fonts/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=application/font-woff", + type: 'asset/resource', + generator: { + filename: "fonts/[name].[ext]", }, }, { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/octet-stream", - options: { - name: "fonts/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=application/octet-stream", + type: 'asset/resource', + generator: { + filename: "fonts/[name].[ext]", }, }, { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, - loader: "file-loader", - options: { - name: "fonts/[name].[ext]", + // use: "file-loader", + type: 'asset/resource', + generator: { + filename: "fonts/[name].[ext]", }, }, { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=image/svg+xml", - options: { - name: "images/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=image/svg+xml", + type: 'asset/resource', + generator: { + filename: "images/[name].[ext]", }, }, { test: /\.(jpg|jpeg|gif|png)$/, - loader: "url-loader?limit=65000&name=images/[name].[ext]", + type: 'asset/resource', + generator: { + filename: "images/[name].[ext]", + }, + // use: "url-loader?limit=65000&name=images/[name].[ext]", }, { - test: /\.(woff|woff2|eot|ttf|otf)$/, - loader: "file-loader", + test: /\.otf(\?v=\d+\.\d+\.\d+)?$/, + // use: "url-loader?limit=10000&mimetype=application/octet-stream", + type: 'asset/resource', + generator: { + filename: "fonts/[name].[ext]", + }, }, ], }, plugins: [ new webpack.DefinePlugin({ "process.env": { - NODE_ENV: `""`, + NODE_ENV: `"development"`, AUTH_SERVER: JSON.stringify(AUTH_SERVER), }, }), - new CopyWebpackPlugin([ - { from: "./src/static", ignore: ["*.html"] }, - "./public/manifest.json", - ]), + new CopyWebpackPlugin({ + patterns:[ + {from: "./src/static"}, + { from: "./node_modules/@voxeet/react-components/dist/fonts", to:'./fonts'}, + { from: "./node_modules/@voxeet/react-components/dist/images", to:'./images'}, + { from: "./node_modules/@voxeet/react-components/dist/sounds", to:'./sounds'}, + "./public/manifest.json", + ] + }), new HtmlWebpackPlugin({ inject: true, template: "./public/index.html", js: /*process.env.ELECTRON ? ["preload.js"] : */[], }), - new webpack.NoEmitOnErrorsPlugin(), + // new webpack.NoEmitOnErrorsPlugin(), + new webpack.HotModuleReplacementPlugin(), ], }; diff --git a/frontend/webpack.config.prod.js b/frontend/webpack.config.prod.js index e8b4560..ddb305e 100644 --- a/frontend/webpack.config.prod.js +++ b/frontend/webpack.config.prod.js @@ -1,9 +1,10 @@ const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); -const ExtractTextPlugin = require("extract-text-webpack-plugin"); -var PrettierPlugin = require("prettier-webpack-plugin"); +const CopyPlugin = require("copy-webpack-plugin"); +const TerserPlugin = require("terser-webpack-plugin"); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); + // Try the environment variable, otherwise use root const ASSET_PATH = process.env.ASSET_PATH || ''; @@ -20,88 +21,122 @@ module.exports = { entry: ["@babel/polyfill", "./src/index.js"], output: { path: path.join(__dirname, "dist"), - filename: "bundle.js", + filename: '[name].bundle.js', + // chunkFilename: '[id].[chunkhash].js', publicPath: ASSET_PATH, }, + mode: 'production', optimization: { splitChunks: { // include all types of chunks chunks: 'all', - maxSize:3000000, + maxSize:5000000, minSize:1000000, - } + cacheGroups: { + commons: { + test: /[\\/]node_modules[\\/]/, + name: "vendor", + chunks: "initial", + }, + }, + }, + minimize: true, + minimizer: [ + new TerserPlugin({ + parallel: true, + }), + ], }, module: { rules: [ { - test: /.js?$/, - loaders: ["babel-loader"], + test: /\.js?$/, + use: ["babel-loader"], include: path.resolve(__dirname), }, { test: /\.css$/, - loaders: ["style-loader", "css-loader"], + use: [ + MiniCssExtractPlugin.loader, + "style-loader", + "css-loader" + ], }, { - test: /.jsx?$/, - loaders: ["babel-loader"], - include: path.resolve(__dirname), + test: /\.less$/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + 'less-loader' + ], }, { - test: /.less$/, - loader: "style-loader!css-loader!less-loader", + test: /\.jsx?$/, + use: ["babel-loader"], + include: path.resolve(__dirname), }, { test: /\.mp3$/, - loader: "file-loader", - options: { - name: "sounds/[name].[ext]", + // use: "file-loader", + type: 'asset/resource', + generator: { + filename: "sounds/[name][ext]", }, }, { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/font-woff", - options: { - name: "fonts/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=application/font-woff", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", }, }, { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/font-woff", - options: { - name: "fonts/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=application/font-woff", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", }, }, { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/octet-stream", - options: { - name: "fonts/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=application/octet-stream", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", }, }, { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, - loader: "file-loader", - options: { - name: "fonts/[name].[ext]", + // use: "file-loader", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", }, }, { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=image/svg+xml", - options: { - name: "images/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=image/svg+xml", + type: 'asset/resource', + generator: { + filename: "images/[name][ext]", }, }, { test: /\.(jpg|jpeg|gif|png)$/, - loader: "url-loader?limit=65000&name=images/[name].[ext]", + type: 'asset/resource', + generator: { + filename: "images/[name][ext]", + }, + // use: "url-loader?limit=65000&name=images/[name].[ext]", }, { test: /\.otf(\?v=\d+\.\d+\.\d+)?$/, - loader: "url-loader?limit=10000&mimetype=application/octet-stream", - options: { - name: "fonts/[name].[ext]", + // use: "url-loader?limit=10000&mimetype=application/octet-stream", + type: 'asset/resource', + generator: { + filename: "fonts/[name][ext]", }, }, ], @@ -114,11 +149,16 @@ module.exports = { AUTH_SERVER: JSON.stringify(AUTH_SERVER), }, }), - new PrettierPlugin(), - new CopyWebpackPlugin([ - { from: "./src/static", ignore: ["*.html"] }, - "./public/manifest.json", - ]), + new CopyPlugin({ + patterns: [ + { from: "./src/static"}, + { from: "./node_modules/@voxeet/react-components/dist/fonts", to:'./fonts'}, + { from: "./node_modules/@voxeet/react-components/dist/images", to:'./images'}, + { from: "./node_modules/@voxeet/react-components/dist/sounds", to:'./sounds'}, + "./public/manifest.json", + ] + }), + new MiniCssExtractPlugin(), new HtmlWebpackPlugin({ inject: true, template: "./public/index.html",