Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

statically compress webpack artifacts #6266

Merged
merged 1 commit into from
Oct 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## v0.12.0

- [cli] enable static compression of build artifacts [#6266](https://github.com/eclipse-theia/theia/pull/6266)
- to disable pass `--no-static-compression` to `theia build` or `theia watch`.

Breaking changes:

- [plugin] don't block web socket with many plugins [6252](https://github.com/eclipse-theia/theia/pull/6252)
Expand All @@ -15,7 +18,7 @@ Breaking changes:
- `PluginDeployerHandler.getPluginMetadata` is replaced with `PluginDeployerHandler.getPluginDependencies` to access plugin dependencies.
- `HostedPluginServer.getDeployedMetadata` is replaced with `HostedPluginServer.getDeployedPluginIds` and `HostedPluginServer.getDeployedPlugins`
to fetch first only ids of deployed plugins and then deployed metadata for only yet not loaded plugins.
- `HostedPluginDeployerHandler.getDeployedFrontendMetadata` and `HostedPluginDeployerHandler.getDeployedBackendMetadata` are replaced with
- `HostedPluginDeployerHandler.getDeployedFrontendMetadata` and `HostedPluginDeployerHandler.getDeployedBackendMetadata` are replaced with
`HostedPluginDeployerHandler.getDeployedFrontendPluginIds`, `HostedPluginDeployerHandlergetDeployedBackendPluginIds` and `HostedPluginDeployerHandler.getDeployedPlugin` to featch first only ids and then deplyoed metadata fro only yet not loaded plugins.
- `PluginHost.init` can initialize plugins asynchronous, synchronous initialization is still supported.
- `HostedPluginReader.doGetPluginMetadata` is renamed to `HostedPluginReader.getPluginMetadata`.
Expand Down
1 change: 1 addition & 0 deletions dev-packages/application-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"babel-loader": "^8.0.6",
"bunyan": "^1.8.10",
"circular-dependency-plugin": "^5.0.0",
"@theia/compression-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^4.5.0",
"css-loader": "^0.28.1",
"electron-rebuild": "^1.8.6",
Expand Down
54 changes: 33 additions & 21 deletions dev-packages/application-manager/src/generator/webpack-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,50 @@ const webpack = require('webpack');
const yargs = require('yargs');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const CompressionPlugin = require('@theia/compression-webpack-plugin')

const outputPath = path.resolve(__dirname, 'lib');
const { mode } = yargs.option('mode', {
const { mode, staticCompression } = yargs.option('mode', {
description: "Mode to use",
choices: ["development", "production"],
default: "production"
}).option('static-compression', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: no-static-compression vs static-compression?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

description: 'Controls whether to enable compression of static artifacts.',
type: 'boolean',
default: true
}).argv;
const development = mode === 'development';${this.ifMonaco(() => `

const monacoEditorCorePath = development ? '${this.resolve('@typefox/monaco-editor-core', 'dev/vs')}' : '${this.resolve('@typefox/monaco-editor-core', 'min/vs')}';
const monacoCssLanguagePath = '${this.resolve('monaco-css', 'release/min')}';
const monacoHtmlLanguagePath = '${this.resolve('monaco-html', 'release/min')}';`)}

const plugins = [new CopyWebpackPlugin([${this.ifMonaco(() => `
{
from: monacoEditorCorePath,
to: 'vs'
},
{
from: monacoCssLanguagePath,
to: 'vs/language/css'
},
{
from: monacoHtmlLanguagePath,
to: 'vs/language/html'
}`)}
])];
// it should go after copy-plugin in order to compress monaco as well
if (staticCompression) {
plugins.push(new CompressionPlugin({
// enable reuse of compressed artifacts for incremental development
cache: development
}));
}
plugins.push(new CircularDependencyPlugin({
exclude: /(node_modules|examples)\\/./,
failOnError: false // https://github.com/nodejs/readable-stream/issues/280#issuecomment-297076462
}));

module.exports = {
entry: path.resolve(__dirname, 'src-gen/frontend/index.js'),
output: {
Expand Down Expand Up @@ -163,26 +194,7 @@ module.exports = {
}`)}
},
devtool: 'source-map',
plugins: [
new CopyWebpackPlugin([${this.ifMonaco(() => `
{
from: monacoEditorCorePath,
to: 'vs'
},
{
from: monacoCssLanguagePath,
to: 'vs/language/css'
},
{
from: monacoHtmlLanguagePath,
to: 'vs/language/html'
}`)}
]),
new CircularDependencyPlugin({
exclude: /(node_modules|examples)\\/./,
failOnError: false // https://github.com/nodejs/readable-stream/issues/280#issuecomment-297076462
}),
],
plugins,
stats: {
warnings: true
}
Expand Down
36 changes: 35 additions & 1 deletion packages/core/src/node/backend-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import * as path from 'path';
import * as http from 'http';
import * as https from 'https';
import * as express from 'express';
import * as yargs from 'yargs';
import * as fs from 'fs-extra';
import { inject, named, injectable } from 'inversify';
import { inject, named, injectable, postConstruct } from 'inversify';
import { ILogger, ContributionProvider, MaybePromise } from '../common';
import { CliContribution } from './cli';
import { Deferred } from '../common/promise-util';
import { environment } from '../common/index';
import { AddressInfo } from 'net';
import { ApplicationPackage } from '@theia/application-package';

export const BackendApplicationContribution = Symbol('BackendApplicationContribution');
export interface BackendApplicationContribution {
Expand Down Expand Up @@ -93,6 +95,9 @@ export class BackendApplication {

protected readonly app: express.Application = express();

@inject(ApplicationPackage)
protected readonly applicationPackage: ApplicationPackage;

constructor(
@inject(ContributionProvider) @named(BackendApplicationContribution)
protected readonly contributionsProvider: ContributionProvider<BackendApplicationContribution>,
Expand Down Expand Up @@ -124,6 +129,17 @@ export class BackendApplication {
}
}
}
}

@postConstruct()
protected init(): void {
this.app.get('*.js', this.serveGzipped.bind(this, 'text/javascript'));
this.app.get('*.js.map', this.serveGzipped.bind(this, 'application/json'));
this.app.get('*.css', this.serveGzipped.bind(this, 'text/css'));
this.app.get('*.wasm', this.serveGzipped.bind(this, 'application/wasm'));
this.app.get('*.gif', this.serveGzipped.bind(this, 'image/gif'));
this.app.get('*.png', this.serveGzipped.bind(this, 'image/png'));
this.app.get('*.svg', this.serveGzipped.bind(this, 'image/svg+xml'));

for (const contribution of this.contributionsProvider.getContributions()) {
if (contribution.configure) {
Expand Down Expand Up @@ -217,4 +233,22 @@ export class BackendApplication {
}
}

protected async serveGzipped(contentType: string, req: express.Request, res: express.Response, next: express.NextFunction): Promise<void> {
const acceptedEncodings = req.acceptsEncodings();

const gzUrl = `${req.url}.gz`;
const gzPath = path.join(this.applicationPackage.projectPath, 'lib', gzUrl);
if (acceptedEncodings.indexOf('gzip') === -1 || !(await fs.pathExists(gzPath))) {
next();
return;
}

req.url = gzUrl;

res.set('Content-Encoding', 'gzip');
res.set('Content-Type', contentType);

next();
}

}
4 changes: 4 additions & 0 deletions packages/task/src/node/test/task-test-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ import taskBackendModule from '../task-backend-module';
import filesystemBackendModule from '@theia/filesystem/lib/node/filesystem-backend-module';
import workspaceServer from '@theia/workspace/lib/node/workspace-backend-module';
import { messagingBackendModule } from '@theia/core/lib/node/messaging/messaging-backend-module';
// tslint:disable-next-line:no-implicit-dependencies
import { ApplicationPackage } from '@theia/application-package/lib/application-package';

export function createTaskTestContainer(): Container {
const testContainer = new Container();

testContainer.load(backendApplicationModule);
testContainer.rebind(ApplicationPackage).toConstantValue({} as ApplicationPackage);

bindLogger(testContainer.bind.bind(testContainer));
testContainer.load(messagingBackendModule);
testContainer.load(processBackendModule);
Expand Down
5 changes: 5 additions & 0 deletions packages/terminal/src/node/test/terminal-test-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ import { backendApplicationModule } from '@theia/core/lib/node/backend-applicati
import processBackendModule from '@theia/process/lib/node/process-backend-module';
import { messagingBackendModule } from '@theia/core/lib/node/messaging/messaging-backend-module';
import terminalBackendModule from '../terminal-backend-module';
// tslint:disable-next-line:no-implicit-dependencies
import { ApplicationPackage } from '@theia/application-package/lib/application-package';

export function createTerminalTestContainer(): Container {
const container = new Container();

container.load(backendApplicationModule);
container.rebind(ApplicationPackage).toConstantValue({} as ApplicationPackage);

bindLogger(container.bind.bind(container));
container.load(messagingBackendModule);
container.load(processBackendModule);
Expand Down
Loading