Add a .env config and explanation how to use HMR

pull/18318/head
Dariusz Niemczyk 2021-08-01 17:05:33 +02:00 committed by Dariusz Niemczyk
parent b677edbc58
commit a9f3f873a5
No known key found for this signature in database
GPG Key ID: 0AD2F70C94CA5B03
6 changed files with 99 additions and 49 deletions

13
.env.example Normal file
View File

@ -0,0 +1,13 @@
# If you want to have proper hot-reload css experience, define one and set this on.
CSS_HOT_RELOAD=1
# Define which one theme you want to load for hot-reload purposes.
# You can load multiple themes at once, but switching between is quite buggy with the hot-reload turned on.
# To use a single theme just uncomment a line with the theme you want to use.
MATRIX_THEMES='light'
#MATRIX_THEMES='dark'
#MATRIX_THEMES='light-legacy'
#MATRIX_THEMES='dark-legacy'
#MATRIX_THEMES='light-custom'
#MATRIX_THEMES='dark-custom'
# If you want to use multiple themes, define the combinations manually like below:
#MATRIX_THEMES='light,dark'

1
.gitignore vendored
View File

@ -21,3 +21,4 @@ electron/pub
/webpack-stats.json /webpack-stats.json
.vscode .vscode
.vscode/ .vscode/
.env

View File

@ -30,14 +30,14 @@ and [element-ios](https://github.com/vector-im/element-ios).
Getting Started Getting Started
=============== ===============
The easiest way to test Element is to just use the hosted copy at https://app.element.io. The easiest way to test Element is to just use the hosted copy at <https://app.element.io>.
The `develop` branch is continuously deployed to https://develop.element.io The `develop` branch is continuously deployed to <https://develop.element.io>
for those who like living dangerously. for those who like living dangerously.
To host your own copy of Element, the quickest bet is to use a pre-built To host your own copy of Element, the quickest bet is to use a pre-built
released version of Element: released version of Element:
1. Download the latest version from https://github.com/vector-im/element-web/releases 1. Download the latest version from <https://github.com/vector-im/element-web/releases>
1. Untar the tarball on your web server 1. Untar the tarball on your web server
1. Move (or symlink) the `element-x.x.x` directory to an appropriate name 1. Move (or symlink) the `element-x.x.x` directory to an appropriate name
1. Configure the correct caching headers in your webserver (see below) 1. Configure the correct caching headers in your webserver (see below)
@ -46,7 +46,7 @@ released version of Element:
1. Enter the URL into your browser and log into Element! 1. Enter the URL into your browser and log into Element!
Releases are signed using gpg and the OpenPGP standard, and can be checked against the public key located Releases are signed using gpg and the OpenPGP standard, and can be checked against the public key located
at https://packages.riot.im/element-release-key.asc. at <https://packages.riot.im/element-release-key.asc>.
Note that for the security of your chats will need to serve Element Note that for the security of your chats will need to serve Element
over HTTPS. Major browsers also do not allow you to use VoIP/video over HTTPS. Major browsers also do not allow you to use VoIP/video
@ -72,7 +72,7 @@ access to Element (or other apps) due to sharing the same domain.
We have put some coarse mitigations into place to try to protect against this We have put some coarse mitigations into place to try to protect against this
situation, but it's still not good practice to do it in the first place. See situation, but it's still not good practice to do it in the first place. See
https://github.com/vector-im/element-web/issues/1977 for more details. <https://github.com/vector-im/element-web/issues/1977> for more details.
Configuration best practices Configuration best practices
---------------------------- ----------------------------
@ -80,15 +80,15 @@ Configuration best practices
Unless you have special requirements, you will want to add the following to Unless you have special requirements, you will want to add the following to
your web server configuration when hosting Element Web: your web server configuration when hosting Element Web:
- The `X-Frame-Options: SAMEORIGIN` header, to prevent Element Web from being * The `X-Frame-Options: SAMEORIGIN` header, to prevent Element Web from being
framed and protect from [clickjacking][owasp-clickjacking]. framed and protect from [clickjacking][owasp-clickjacking].
- The `frame-ancestors 'none'` directive to your `Content-Security-Policy` * The `frame-ancestors 'none'` directive to your `Content-Security-Policy`
header, as the modern replacement for `X-Frame-Options` (though both should be header, as the modern replacement for `X-Frame-Options` (though both should be
included since not all browsers support it yet, see included since not all browsers support it yet, see
[this][owasp-clickjacking-csp]). [this][owasp-clickjacking-csp]).
- The `X-Content-Type-Options: nosniff` header, to [disable MIME * The `X-Content-Type-Options: nosniff` header, to [disable MIME
sniffing][mime-sniffing]. sniffing][mime-sniffing].
- The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in * The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in
legacy browsers. legacy browsers.
[mime-sniffing]: [mime-sniffing]:
@ -127,10 +127,10 @@ guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it alread
1. Clone the repo: `git clone https://github.com/vector-im/element-web.git`. 1. Clone the repo: `git clone https://github.com/vector-im/element-web.git`.
1. Switch to the element-web directory: `cd element-web`. 1. Switch to the element-web directory: `cd element-web`.
1. Install the prerequisites: `yarn install`. 1. Install the prerequisites: `yarn install`.
* If you're using the `develop` branch, then it is recommended to set up a * If you're using the `develop` branch, then it is recommended to set up a
proper development environment (see [Setting up a dev proper development environment (see [Setting up a dev
environment](#setting-up-a-dev-environment) below). Alternatively, you environment](#setting-up-a-dev-environment) below). Alternatively, you
can use https://develop.element.io - the continuous integration release of can use <https://develop.element.io> - the continuous integration release of
the develop branch. the develop branch.
1. Configure the app by copying `config.sample.json` to `config.json` and 1. Configure the app by copying `config.sample.json` to `config.json` and
modifying it. See the [configuration docs](docs/config.md) for details. modifying it. See the [configuration docs](docs/config.md) for details.
@ -148,15 +148,16 @@ Running as a Desktop app
======================== ========================
Element can also be run as a desktop app, wrapped in Electron. You can download a Element can also be run as a desktop app, wrapped in Electron. You can download a
pre-built version from https://element.io/get-started or, if you prefer, pre-built version from <https://element.io/get-started> or, if you prefer,
build it yourself. build it yourself.
To build it yourself, follow the instructions at https://github.com/vector-im/element-desktop. To build it yourself, follow the instructions at <https://github.com/vector-im/element-desktop>.
Many thanks to @aviraldg for the initial work on the Electron integration. Many thanks to @aviraldg for the initial work on the Electron integration.
Other options for running as a desktop app: Other options for running as a desktop app:
* @asdf:matrix.org points out that you can use nativefier and it just works(tm)
* @asdf:matrix.org points out that you can use nativefier and it just works(tm)
```bash ```bash
yarn global add nativefier yarn global add nativefier
@ -171,6 +172,7 @@ Running from Docker
The Docker image can be used to serve element-web as a web server. The easiest way to use The Docker image can be used to serve element-web as a web server. The easiest way to use
it is to use the prebuilt image: it is to use the prebuilt image:
```bash ```bash
docker run -p 80:80 vectorim/element-web docker run -p 80:80 vectorim/element-web
``` ```
@ -178,11 +180,13 @@ docker run -p 80:80 vectorim/element-web
To supply your own custom `config.json`, map a volume to `/app/config.json`. For example, To supply your own custom `config.json`, map a volume to `/app/config.json`. For example,
if your custom config was located at `/etc/element-web/config.json` then your Docker command if your custom config was located at `/etc/element-web/config.json` then your Docker command
would be: would be:
```bash ```bash
docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web
``` ```
To build the image yourself: To build the image yourself:
```bash ```bash
git clone https://github.com/vector-im/element-web.git element-web git clone https://github.com/vector-im/element-web.git element-web
cd element-web cd element-web
@ -192,6 +196,7 @@ docker build .
If you're building a custom branch, or want to use the develop branch, check out the appropriate If you're building a custom branch, or want to use the develop branch, check out the appropriate
element-web branch and then run: element-web branch and then run:
```bash ```bash
docker build -t \ docker build -t \
--build-arg USE_CUSTOM_SDKS=true \ --build-arg USE_CUSTOM_SDKS=true \
@ -224,6 +229,7 @@ Caching requirements
==================== ====================
Element requires the following URLs not to be cached, when/if you are serving Element from your own webserver: Element requires the following URLs not to be cached, when/if you are serving Element from your own webserver:
``` ```
/config.*.json /config.*.json
/i18n /i18n
@ -261,6 +267,10 @@ internet. So please don't depend on resources (JS libs, CSS, images, fonts)
hosted by external CDNs or servers but instead please package all dependencies hosted by external CDNs or servers but instead please package all dependencies
into Element itself. into Element itself.
CSS hot-reload is currently an opt-in development feature, and if you want to have
it working properly on your environment, create a `.env` file in this repository
with proper environmental, see `.env.example` for documentation and example.
Setting up a dev environment Setting up a dev environment
============================ ============================
@ -302,14 +312,15 @@ yarn reskindex
yarn start yarn start
``` ```
Wait a few seconds for the initial build to finish; you should see something like: Wait a few seconds for the initial build to finish; you should see something like:
``` ```
[element-js] <s> [webpack.Progress] 100% [element-js] <s> [webpack.Progress] 100%
[element-js] [element-js]
[element-js] 「wdm」: 1840 modules [element-js] 「wdm」: 1840 modules
[element-js] 「wdm」: Compiled successfully. [element-js] 「wdm」: Compiled successfully.
``` ```
Remember, the command will not terminate since it runs the web server Remember, the command will not terminate since it runs the web server
and rebuilds source files when they change. This development server also and rebuilds source files when they change. This development server also
disables caching, so do NOT use it in production. disables caching, so do NOT use it in production.
@ -317,7 +328,7 @@ Wait a few seconds for the initial build to finish; you should see something lik
Configure the app by copying `config.sample.json` to `config.json` and Configure the app by copying `config.sample.json` to `config.json` and
modifying it. See the [configuration docs](docs/config.md) for details. modifying it. See the [configuration docs](docs/config.md) for details.
Open http://127.0.0.1:8080/ in your browser to see your newly built Element. Open <http://127.0.0.1:8080/> in your browser to see your newly built Element.
**Note**: The build script uses inotify by default on Linux to monitor directories **Note**: The build script uses inotify by default on Linux to monitor directories
for changes. If the inotify limits are too low your build will fail silently or with for changes. If the inotify limits are too low your build will fail silently or with
@ -393,14 +404,14 @@ Triaging issues
We strive to completely cover all applicable issues with these core labels: We strive to completely cover all applicable issues with these core labels:
1. __Type__ — Every issue is assigned a type: 1. __Type__ — Every issue is assigned a type:
- __[T-Defect](https://github.com/vector-im/element-web/labels/T-Defect):__ * __[T-Defect](https://github.com/vector-im/element-web/labels/T-Defect):__
Bugs, crashes, hangs, vulnerabilities, or other reported problems Bugs, crashes, hangs, vulnerabilities, or other reported problems
- __[T-Enhancement](https://github.com/vector-im/element-web/labels/T-Enhancement):__ * __[T-Enhancement](https://github.com/vector-im/element-web/labels/T-Enhancement):__
New features, changes in functionality, performance boosts, user-facing New features, changes in functionality, performance boosts, user-facing
improvements improvements
- __[T-Task](https://github.com/vector-im/element-web/labels/T-Task):__ * __[T-Task](https://github.com/vector-im/element-web/labels/T-Task):__
Refactoring, enabling or disabling functionality, other engineering tasks Refactoring, enabling or disabling functionality, other engineering tasks
- __[T-Other](https://github.com/vector-im/element-web/labels/T-Other):__ * __[T-Other](https://github.com/vector-im/element-web/labels/T-Other):__
Questions, user support, anything else Questions, user support, anything else
2. __Severity__ — All issues labeled `T-Defect` are also assigned a severity: 2. __Severity__ — All issues labeled `T-Defect` are also assigned a severity:

View File

@ -104,6 +104,7 @@
"concurrently": "^5.3.0", "concurrently": "^5.3.0",
"cpx": "^1.5.0", "cpx": "^1.5.0",
"css-loader": "^3.6.0", "css-loader": "^3.6.0",
"dotenv": "^10.0.0",
"eslint": "7.18.0", "eslint": "7.18.0",
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main", "eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main",

View File

@ -1,5 +1,6 @@
/* eslint-disable quote-props */ /* eslint-disable quote-props */
const dotenv = require('dotenv');
const path = require('path'); const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin');
@ -21,24 +22,29 @@ const cssThemes = {
"theme-dark-custom": "./node_modules/matrix-react-sdk/res/themes/dark-custom/css/dark-custom.scss", "theme-dark-custom": "./node_modules/matrix-react-sdk/res/themes/dark-custom/css/dark-custom.scss",
}; };
function getActiveThemes() { let dotenvConfig = { parsed: {} };
const theme = process.env.MATRIX_THEMES ?? 'light,dark'; try {
const themes = theme.split(',').filter(x => x).map(x => x.trim()).filter(x => x); dotenvConfig = dotenv.config();
return themes; } catch (err) {
dotenvConfig = {
parsed: {
CSS_HOT_RELOAD: 0,
MATRIX_THEMES: 'light',
},
};
} }
const ACTIVE_THEMES = getActiveThemes(); const CSS_HOT_RELOAD = process.env.CSS_HOT_RELOAD ?? dotenvConfig.CSS_HOT_RELOAD;
function getThemesImports() { const MATRIX_THEMES = process.env.MATRIX_THEMES ?? dotenvConfig.MATRIX_THEMES;
const imports = ACTIVE_THEMES.map((t, index) => {
const themeImportPath = cssThemes[`theme-${t}`].replace('./node_modules/', ''); function getActiveThemes() {
return themeImportPath; // We want to use `light` theme by default if it's not defined.
}); const theme = MATRIX_THEMES;
const s = JSON.stringify(ACTIVE_THEMES); const themes = theme.split(',').filter(x => x).map(x => x.trim()).filter(x => x);
return ` if (themes.length > 1) {
window.MX_insertedThemeStylesCounter = 0 throw new Error('Please see `.env.example` for proper hotreload&themes configuation.');
window.MX_DEV_ACTIVE_THEMES = (${s}); }
${imports.map(i => `import("${i}")`).join('\n')}; return themes;
`;
} }
module.exports = (env, argv) => { module.exports = (env, argv) => {
@ -57,6 +63,7 @@ module.exports = (env, argv) => {
nodeEnv = "production"; nodeEnv = "production";
} }
const devMode = nodeEnv !== 'production'; const devMode = nodeEnv !== 'production';
const useCssHotReload = CSS_HOT_RELOAD === '1' && devMode;
const development = {}; const development = {};
if (argv.mode === "production") { if (argv.mode === "production") {
@ -73,16 +80,22 @@ module.exports = (env, argv) => {
const reactSdkSrcDir = path.resolve(require.resolve("matrix-react-sdk/package.json"), '..', 'src'); const reactSdkSrcDir = path.resolve(require.resolve("matrix-react-sdk/package.json"), '..', 'src');
const jsSdkSrcDir = path.resolve(require.resolve("matrix-js-sdk/package.json"), '..', 'src'); const jsSdkSrcDir = path.resolve(require.resolve("matrix-js-sdk/package.json"), '..', 'src');
const ACTIVE_THEMES = getActiveThemes();
function getThemesImports() {
const imports = ACTIVE_THEMES.map((t, index) => {
const themeImportPath = cssThemes[`theme-${ t }`].replace('./node_modules/', '');
return themeImportPath;
});
const s = JSON.stringify(ACTIVE_THEMES);
return `
window.MX_insertedThemeStylesCounter = 0
window.MX_DEV_ACTIVE_THEMES = (${ s });
${ imports.map(i => `import("${ i }")`).join('\n') };
`;
}
return { return {
...development, ...development,
watch: true,
watchOptions: {
aggregateTimeout: 200,
poll: 1000,
ignored: [/node_modules([\\]+|\/)+(?!matrix-react-sdk|matrix-js-sdk)/],
},
node: { node: {
// Mock out the NodeFS module: The opus decoder imports this wrongly. // Mock out the NodeFS module: The opus decoder imports this wrongly.
fs: 'empty', fs: 'empty',
@ -94,7 +107,7 @@ module.exports = (env, argv) => {
"jitsi": "./src/vector/jitsi/index.ts", "jitsi": "./src/vector/jitsi/index.ts",
"usercontent": "./node_modules/matrix-react-sdk/src/usercontent/index.js", "usercontent": "./node_modules/matrix-react-sdk/src/usercontent/index.js",
"recorder-worklet": "./node_modules/matrix-react-sdk/src/audio/RecorderWorklet.ts", "recorder-worklet": "./node_modules/matrix-react-sdk/src/audio/RecorderWorklet.ts",
...(devMode ? {} : cssThemes), ...(useCssHotReload ? {} : cssThemes),
}, },
optimization: { optimization: {
@ -178,7 +191,7 @@ module.exports = (env, argv) => {
/olm[\\/](javascript[\\/])?olm\.js$/, /olm[\\/](javascript[\\/])?olm\.js$/,
], ],
rules: [ rules: [
devMode && { useCssHotReload && {
test: /devcss\.ts$/, test: /devcss\.ts$/,
loader: 'string-replace-loader', loader: 'string-replace-loader',
options: { options: {
@ -217,7 +230,7 @@ module.exports = (env, argv) => {
{ {
test: /\.css$/, test: /\.css$/,
use: [ use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader, MiniCssExtractPlugin.loader,
{ {
loader: 'css-loader', loader: 'css-loader',
options: { options: {
@ -271,8 +284,14 @@ module.exports = (env, argv) => {
* of the JS/TS files. * of the JS/TS files.
* Should be MUCH better with webpack 5, but we're stuck to this solution for now. * Should be MUCH better with webpack 5, but we're stuck to this solution for now.
*/ */
devMode ? { useCssHotReload ? {
loader: 'style-loader', options: { loader: 'style-loader', options: {
/**
* If we refactor the `theme.js` in `matrix-react-sdk` a little bit,
* we could try using `lazyStyleTag` here to add and remove styles on demand,
* that would nicely resolve issues of race conditions for themes,
* at least for development purposes.
*/
attributes: { attributes: {
'data-mx-theme': 'replace_me', 'data-mx-theme': 'replace_me',
}, },
@ -430,7 +449,7 @@ module.exports = (env, argv) => {
}, },
], ],
}, },
], ].filter(Boolean),
}, },
plugins: [ plugins: [

View File

@ -4024,6 +4024,11 @@ dot-prop@^5.2.0:
dependencies: dependencies:
is-obj "^2.0.0" is-obj "^2.0.0"
dotenv@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
duplexer@^0.1.1: duplexer@^0.1.1:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"