feat: support monaco editor worker (#3703)

This commit is contained in:
野声 2024-05-22 15:52:05 +08:00 committed by GitHub
parent 0aa3838b84
commit f5cedc4cf4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 306 additions and 100 deletions

View File

@ -8,6 +8,7 @@ node_modules
**/tools/playwright/lib/**
**/tools/cli-engine/lib/**
tools/cli-engine/src/browser/worker-host.js
packages/monaco/worker/**
**/typings/**
**/scripts/**

View File

@ -8,6 +8,9 @@ on:
required: true
default: 'main'
env:
NODE_ENV: production
jobs:
rc-version:
name: RC Version

View File

@ -12,6 +12,9 @@ on:
description: 'The release branch, eg: v3.xx, main'
required: false
env:
NODE_ENV: production
jobs:
release:
name: Release

View File

@ -4,6 +4,7 @@ node_modules
**/tools/extensions/**
**/tools/**/vendor/
tools/cli-engine/src/browser/worker-host.js
packages/monaco/worker/**
**/typings/**
packages/*/lib/**

View File

@ -4,7 +4,7 @@
"license": "MIT",
"scripts": {
"preinstall": "node scripts/preinstall.js && husky install",
"clean": "rimraf \"./packages/*/lib\"",
"clean": "rimraf \"./packages/*/lib\" && lerna run clean",
"check:dep": "tsx ./scripts/depcheck",
"init": "yarn run clean && yarn run build:all",
"start": "yarn run rebuild:node && cross-env HOST=127.0.0.1 WS_PATH=ws://127.0.0.1:8000 NODE_ENV=development tsx ./scripts/start",
@ -19,11 +19,12 @@
"add:node": "tsx ./scripts/add-node",
"add:browser": "tsx ./scripts/add-browser",
"build": "yarn run compile",
"build:all": "yarn run build && yarn run build:worker-host && yarn run build:ext-host && yarn run build:components",
"build:all": "yarn run build && yarn run build:worker-host && yarn run build:ext-host && yarn run build:components && yarn build:monaco-worker",
"compile": "cross-env NODE_ENV=production tsx ./scripts/build",
"build:worker-host": "cd packages/extension && yarn run compile:worker",
"build:ext-host": "cd packages/extension && yarn run build:ext-host",
"build:cli-engine": "cd tools/cli-engine && yarn run build",
"build:monaco-worker": "cd packages/monaco && yarn run build:worker",
"watch:ext-host": "cd packages/extension && yarn run watch:ext-host",
"watch:worker-host": "cd packages/extension && yarn run watch:worker",
"watch": "yarn run rebuild:node && cross-env NODE_ENV=production tsx ./scripts/watch",
@ -133,7 +134,8 @@
"tslib": "^2.6.2",
"tsx": "^4.7.1",
"typescript": "4.9.3",
"webpack": "^5.90.0"
"webpack": "^5.90.0",
"webpack-manifest-plugin": "^5.0.0"
},
"workspaces": [
"packages/*",

View File

@ -4,12 +4,12 @@ import { Injector } from '@opensumi/di';
import { LanguageParserService } from '@opensumi/ide-ai-native/lib/browser/languages/service';
import { AppConfig, BrowserModule } from '@opensumi/ide-core-browser';
import { ESupportRuntime } from '@opensumi/ide-core-browser/lib/application/runtime';
import { IRendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
import { RendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
import { Uri } from '@opensumi/ide-core-common';
import { MockInjector } from '@opensumi/ide-dev-tool/src/mock-injector';
class MockRendererRuntime implements IRendererRuntime {
runtimeName: ESupportRuntime;
class MockRendererRuntime extends RendererRuntime {
runtimeName = 'web' as ESupportRuntime;
mergeAppConfig(meta: AppConfig): AppConfig {
throw new Error('Method not implemented.');
}
@ -34,7 +34,7 @@ describe.skip('tree sitter', () => {
useClass: LanguageParserService,
},
]);
injector.mockService(IRendererRuntime, new MockRendererRuntime());
injector.mockService(RendererRuntime, new MockRendererRuntime());
});
it('parser', async () => {

View File

@ -1,7 +1,7 @@
import Parser from 'web-tree-sitter';
import { Autowired, Injectable } from '@opensumi/di';
import { EKnownResources, IRendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
import { EKnownResources, RendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
import { Deferred } from '@opensumi/ide-utils';
/**
@ -13,8 +13,8 @@ export class WasmModuleManager {
private cachedRuntime: Map<string, Deferred<ArrayBuffer>> = new Map();
@Autowired(IRendererRuntime)
rendererRuntime: IRendererRuntime;
@Autowired(RendererRuntime)
rendererRuntime: RendererRuntime;
private async resolveResourceUri() {
const uri = await this.rendererRuntime.provideResourceUri(EKnownResources.TreeSitterWasmDirectory);

View File

@ -1,38 +1,19 @@
import { Autowired, Injectable, Injector } from '@opensumi/di';
import { Injectable, Injector } from '@opensumi/di';
import { BrowserModule } from '../../../browser-module';
import { AppConfig } from '../../../react-providers';
import { ESupportRuntime, onigWasmCDNUri, treeSitterWasmCDNUri } from '../constants';
import { EKnownResources, IRendererRuntime } from '../types';
import { ESupportRuntime } from '../constants';
import { RendererRuntime } from '../types';
import { injectBrowserInnerProviders } from './inner-providers-browser';
@Injectable()
export class BrowserRuntime implements IRendererRuntime {
export class BrowserRuntime extends RendererRuntime {
runtimeName = ESupportRuntime.Web;
@Autowired(AppConfig)
appConfig: AppConfig;
registerRuntimeModuleProviders(injector: Injector, instance: BrowserModule<any>): void {
instance.webProviders && injector.addProviders(...instance.webProviders);
}
registerRuntimeInnerProviders(injector: Injector): void {
injectBrowserInnerProviders(injector);
}
mergeAppConfig(meta: AppConfig): AppConfig {
return meta;
}
async provideResourceUri(resource: EKnownResources): Promise<string> {
switch (resource) {
case EKnownResources.OnigWasm:
return this.appConfig.onigWasmUri || onigWasmCDNUri;
case EKnownResources.TreeSitterWasmDirectory:
return this.appConfig.treeSitterWasmDirectoryUri || treeSitterWasmCDNUri;
default:
throw new Error(`Unknown resource: ${resource}`);
}
}
}

View File

@ -1,18 +1,15 @@
import { Autowired, Injectable, Injector } from '@opensumi/di';
import { Injectable, Injector } from '@opensumi/di';
import { BrowserModule } from '../../../browser-module';
import { AppConfig } from '../../../react-providers';
import { electronEnv } from '../../../utils/electron';
import { ESupportRuntime, onigWasmCDNUri, treeSitterWasmCDNUri } from '../constants';
import { EKnownResources, IRendererRuntime } from '../types';
import { EKnownResources, RendererRuntime } from '../types';
import { injectElectronInnerProviders } from './inner-providers-electron';
@Injectable()
export class ElectronRendererRuntime implements IRendererRuntime {
@Autowired(AppConfig)
appConfig: AppConfig;
export class ElectronRendererRuntime extends RendererRuntime {
runtimeName = ESupportRuntime.Electron;
registerRuntimeModuleProviders(injector: Injector, instance: BrowserModule<any>): void {
@ -21,11 +18,12 @@ export class ElectronRendererRuntime implements IRendererRuntime {
registerRuntimeInnerProviders(injector: Injector): void {
injectElectronInnerProviders(injector);
}
mergeAppConfig(meta: AppConfig): AppConfig {
override mergeAppConfig(meta: AppConfig): AppConfig {
return mergeElectronMetadata(meta);
}
async provideResourceUri(resource: EKnownResources): Promise<string> {
override async provideResourceUri(resource: EKnownResources): Promise<string> {
switch (resource) {
case EKnownResources.OnigWasm:
return electronEnv.onigWasmUri || this.appConfig.onigWasmUri || onigWasmCDNUri;

View File

@ -1,6 +1,10 @@
import type { ESupportRuntime } from './constants';
import { Autowired, Injectable } from '@opensumi/di';
import { AppConfig } from '../../react-providers/config-provider';
import { type ESupportRuntime, onigWasmCDNUri, treeSitterWasmCDNUri } from './constants';
import type { BrowserModule } from '../../browser-module';
import type { AppConfig } from '../../react-providers/config-provider';
import type { Injector } from '@opensumi/di';
export enum EKnownResources {
@ -8,13 +12,28 @@ export enum EKnownResources {
TreeSitterWasmDirectory = 'wasm:tree-sitter',
}
export const IRendererRuntime = Symbol('IRendererRuntime');
export interface IRendererRuntime {
runtimeName: ESupportRuntime;
@Injectable()
export abstract class RendererRuntime {
@Autowired(AppConfig)
protected appConfig: AppConfig;
mergeAppConfig(meta: AppConfig): AppConfig;
registerRuntimeInnerProviders(injector: Injector): void;
registerRuntimeModuleProviders(injector: Injector, module: BrowserModule): void;
abstract runtimeName: ESupportRuntime;
provideResourceUri(resource: EKnownResources): Promise<string>;
abstract registerRuntimeInnerProviders(injector: Injector): void;
abstract registerRuntimeModuleProviders(injector: Injector, module: BrowserModule): void;
mergeAppConfig(meta: AppConfig): AppConfig {
return meta;
}
async provideResourceUri(resource: string): Promise<string> {
switch (resource) {
case EKnownResources.OnigWasm:
return this.appConfig.onigWasmUri || onigWasmCDNUri;
case EKnownResources.TreeSitterWasmDirectory:
return this.appConfig.treeSitterWasmDirectoryUri || treeSitterWasmCDNUri;
default:
throw new Error(`Unknown resource: ${resource}`);
}
}
}

View File

@ -29,6 +29,7 @@ import {
StorageProvider,
StorageResolverContribution,
SupportLogNamespace,
URI,
UrlProvider,
asExtensionCandidate,
createContributionProvider,
@ -49,7 +50,7 @@ import { ESupportRuntime, ElectronConnectionHelper, WebConnectionHelper } from '
import { CONNECTION_HELPER_TOKEN } from '../application/runtime/base-socket';
import { BrowserRuntime } from '../application/runtime/browser';
import { ElectronRendererRuntime } from '../application/runtime/electron-renderer';
import { IRendererRuntime } from '../application/runtime/types';
import { RendererRuntime } from '../application/runtime/types';
import { BrowserModule, IClientApp } from '../browser-module';
import { ClientAppContribution } from '../common';
import { CorePreferences, injectCorePreferences } from '../core-preferences';
@ -156,7 +157,7 @@ export class ClientApp implements IClientApp, IDisposable {
this.injector.addProviders({ token: AppConfig, useValue: this.config });
this.runtime = isDesktop ? this.injector.get(ElectronRendererRuntime) : this.injector.get(BrowserRuntime);
this.injector.addProviders({ token: IRendererRuntime, useValue: this.runtime });
this.injector.addProviders({ token: RendererRuntime, useValue: this.runtime });
if (this.config.devtools) {
// set a global so the opensumi devtools can identify that
@ -586,7 +587,7 @@ export class ClientApp implements IClientApp, IDisposable {
});
injector.addProviders({
token: StorageProvider,
useFactory: () => (storageId) => injector.get(DefaultStorageProvider).get(storageId),
useFactory: (injector) => (storageId: URI) => injector.get(DefaultStorageProvider).get(storageId),
});
createContributionProvider(injector, StorageResolverContribution);
}

View File

@ -19,6 +19,7 @@ export abstract class BrowserModule<T = any> extends BasicModule {
protected app: IClientApp;
public preferences?: (inject: Injector) => void;
public component?: React.ComponentType<T>;
// 脱离于layout渲染的模块
// 脱离于文档流的模块
public isOverlay?: boolean;
}

View File

@ -21,6 +21,7 @@ export * from './design';
// 前端工具方法
export * from './logger';
export * from './utils';
export * from './worker';
export * from './context-key';

View File

@ -223,7 +223,7 @@ export interface AppConfig {
*/
workspaceSuffixName?: string;
/**
* CDN
* /使 CDN
* 'alipay'
*/
componentCDNType?: TComponentCDNType;
@ -305,3 +305,27 @@ export function ConfigProvider(props: React.PropsWithChildren<{ value: AppConfig
}
export type TComponentCDNType = 'unpkg' | 'jsdelivr' | 'alipay' | 'npmmirror';
type IComponentCDNTypeMap = Record<TComponentCDNType, string>;
const CDN_TYPE_MAP: IComponentCDNTypeMap = {
alipay: 'https://gw.alipayobjects.com/os/lib',
npmmirror: 'https://registry.npmmirror.com',
unpkg: 'https://unpkg.com/browse',
jsdelivr: 'https://cdn.jsdelivr.net/npm',
};
export function getCdnHref(
packageName: string,
filePath: string,
version: string,
cdnType: TComponentCDNType = 'alipay',
) {
if (cdnType === 'alipay') {
return `${CDN_TYPE_MAP['alipay']}/${packageName.slice(1)}/${version}/${filePath}`;
} else if (cdnType === 'npmmirror') {
return `${CDN_TYPE_MAP['npmmirror']}/${packageName}/${version}/files/${filePath}`;
} else {
return `${CDN_TYPE_MAP[cdnType]}/${packageName}@${version}/${filePath}`;
}
}

View File

@ -25,6 +25,10 @@ export class StaticResourceServiceImpl implements StaticResourceService {
};
}
public removeStaticResourceProvider(scheme: string) {
this.providers.delete(scheme);
}
public resolveStaticResource(uri: URI): URI {
if (!this.providers.has(uri.scheme)) {
return uri;

View File

@ -0,0 +1,19 @@
export function getWorkerBootstrapUrl(scriptPath: string, label: string, ignoreCors?: boolean): string {
if (ignoreCors) {
return scriptPath;
}
if (/^(http:)|(https:)|(file:)/.test(scriptPath)) {
const currentUrl = String(window.location);
const currentOrigin = currentUrl.substr(
0,
currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length,
);
if (scriptPath.substring(0, currentOrigin.length) !== currentOrigin) {
const js = `/*${label}*/importScripts('${scriptPath}');/*${label}*/`;
const blob = new Blob([js], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
}
return scriptPath;
}

View File

@ -46,4 +46,14 @@ export namespace Schemes {
export const userStorage = 'user_storage';
export const design = 'design';
/**
* Scheme used for loading the WebAssembly files.
*/
export const wasm = 'wasm';
/**
* Scheme used to loading the monaco utilities.
*/
export const monaco = 'monaco';
}

View File

@ -18,7 +18,7 @@ import {
getDebugLogger,
parseWithComments,
} from '@opensumi/ide-core-browser';
import { EKnownResources, IRendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
import { EKnownResources, RendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
import { Disposable, URI, isObject } from '@opensumi/ide-core-common';
import { IFileServiceClient } from '@opensumi/ide-file-service/lib/common';
import {
@ -111,8 +111,8 @@ export class TextmateService extends WithEventBus implements ITextmateTokenizerS
@Autowired(IEditorDocumentModelService)
editorDocumentModelService: IEditorDocumentModelService;
@Autowired(IRendererRuntime)
private rendererRuntime: IRendererRuntime;
@Autowired(RendererRuntime)
private rendererRuntime: RendererRuntime;
public grammarRegistry: Registry;

View File

@ -1,19 +1 @@
export function getWorkerBootstrapUrl(scriptPath: string, label: string, ignoreCors?: boolean): string {
if (ignoreCors) {
return scriptPath;
}
if (/^(http:)|(https:)|(file:)/.test(scriptPath)) {
const currentUrl = String(window.location);
const currentOrigin = currentUrl.substr(
0,
currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length,
);
if (scriptPath.substring(0, currentOrigin.length) !== currentOrigin) {
const js = `/*${label}*/importScripts('${scriptPath}');/*${label}*/`;
const blob = new Blob([js], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
}
return scriptPath;
}
export { getWorkerBootstrapUrl } from '@opensumi/ide-core-browser';

View File

@ -3,7 +3,13 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import { ComponentContextProvider, IIconResourceOptions, IconContext } from '@opensumi/ide-components';
import { DisposableCollection, LabelService, TComponentCDNType, useInjectable } from '@opensumi/ide-core-browser';
import {
DisposableCollection,
LabelService,
TComponentCDNType,
getCdnHref as getCdnHrefRaw,
useInjectable,
} from '@opensumi/ide-core-browser';
import { ExtensionBrowserStyleSheet, URI, localize } from '@opensumi/ide-core-common';
import {
IIconService,
@ -25,15 +31,6 @@ function cloneNode<T>(head): T {
return head.cloneNode(true);
}
type IComponentCDNTypeMap = Record<TComponentCDNType, string>;
const CDN_TYPE_MAP: IComponentCDNTypeMap = {
alipay: 'https://gw.alipayobjects.com/os/lib',
npmmirror: 'https://registry.npmmirror.com',
unpkg: 'https://unpkg.com/browse',
jsdelivr: 'https://cdn.jsdelivr.net/npm',
};
/**
* clone Shadow DOM head proxiedHead
* style proxiedHead
@ -76,13 +73,7 @@ function useMutationObserver(from: HTMLHeadElement, target: HTMLHeadElement) {
const packageName = '@opensumi/ide-components';
function getCdnHref(filePath: string, version: string, cdnType: TComponentCDNType = 'alipay') {
if (cdnType === 'alipay') {
return `${CDN_TYPE_MAP['alipay']}/${packageName.slice(1)}/${version}/${filePath}`;
} else if (cdnType === 'npmmirror') {
return `${CDN_TYPE_MAP['npmmirror']}/${packageName}/${version}/files/${filePath}`;
} else {
return `${CDN_TYPE_MAP[cdnType]}/${packageName}@${version}/${filePath}`;
}
return getCdnHrefRaw(packageName, filePath, version, cdnType);
}
function getStyleSheet(href: string) {

1
packages/monaco/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
worker

View File

@ -3,14 +3,17 @@
"version": "3.0.2",
"files": [
"lib",
"src"
"src",
"worker"
],
"license": "MIT",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"scripts": {
"prepublishOnly": "yarn run build",
"build": "tsc --build ../../configs/ts/references/tsconfig.monaco.json"
"prepublishOnly": "yarn build",
"build": "tsc --build ../../configs/ts/references/tsconfig.monaco.json && yarn build:worker",
"build:worker": "../../node_modules/.bin/webpack --config webpack.config.js",
"clean": "rimraf worker"
},
"dependencies": {
"@opensumi/ide-core-browser": "workspace:*",

View File

@ -1,5 +1,6 @@
import { Autowired, INJECTOR_TOKEN, Injector } from '@opensumi/di';
import {
AppConfig,
ClientAppContribution,
CommandContribution,
ContributionProvider,
@ -21,6 +22,10 @@ import {
PreferenceScope,
PreferenceService,
ServiceNames,
StaticResourceContribution,
StaticResourceService,
getCdnHref,
getWorkerBootstrapUrl,
} from '@opensumi/ide-core-browser';
import {
IMenuItem,
@ -33,6 +38,7 @@ import {
CommandService,
DisposableCollection,
ILogger,
Schemes,
URI,
isOSX,
isString,
@ -90,9 +96,42 @@ import { KEY_CODE_MAP } from './monaco.keycode-map';
import { MonacoResolvedKeybinding } from './monaco.resolved-keybinding';
import { MonacoTelemetryService } from './telemetry.service';
@Domain(ClientAppContribution, CommandContribution, MenuContribution, KeybindingContribution)
const pkgJson = require('../../package.json');
export interface Environment {
/**
* A web worker factory.
* NOTE: If `getWorker` is defined, `getWorkerUrl` is not invoked.
*/
getWorker?(workerId: string, label: string): Promise<Worker> | Worker;
/**
* Return the location for web worker scripts.
* NOTE: If `getWorker` is defined, `getWorkerUrl` is not invoked.
*/
getWorkerUrl?(workerId: string, label: string): string;
}
interface Window {
MonacoEnvironment?: Environment | undefined;
}
const packageName = pkgJson.name;
const packageVersion = pkgJson.version;
@Domain(
ClientAppContribution,
CommandContribution,
MenuContribution,
KeybindingContribution,
StaticResourceContribution,
)
export class MonacoClientContribution
implements ClientAppContribution, CommandContribution, MenuContribution, KeybindingContribution
implements
ClientAppContribution,
CommandContribution,
MenuContribution,
KeybindingContribution,
StaticResourceContribution
{
@Autowired(MonacoContribution)
private readonly monacoContributionProvider: ContributionProvider<MonacoContribution>;
@ -151,6 +190,12 @@ export class MonacoClientContribution
@Autowired(KeybindingRegistry)
private readonly keybindings: KeybindingRegistry;
@Autowired(StaticResourceService)
private readonly staticResourceService: StaticResourceService;
@Autowired(AppConfig)
private readonly appConfig: AppConfig;
get editorExtensionsRegistry(): typeof EditorExtensionsRegistry {
return EditorExtensionsRegistry;
}
@ -215,6 +260,9 @@ export class MonacoClientContribution
// 监听 preferences 更新事件,同步更新 mime
this.setPreferencesChangeListener();
// 注册 monaco environment
this.registerMonacoEnvironment();
// 修改一些 Monaco 内置 Services 的行为
this.patchMonacoInternalServices();
@ -228,6 +276,28 @@ export class MonacoClientContribution
this.keybindings.onKeybindingsChanged(() => this.updateMonacoKeybindings());
}
registerMonacoEnvironment() {
const defaultEnvironment = (window as Window).MonacoEnvironment || ({} as Environment);
(window as Window).MonacoEnvironment = {
getWorkerUrl: (moduleId, label) => {
const result = this.staticResourceService.resolveStaticResource(
URI.from({
scheme: Schemes.monaco,
path: 'worker',
query: JSON.stringify({ moduleId, label }),
}),
);
if (result.scheme === Schemes.monaco) {
throw new Error(`Unsupported monaco worker: ${moduleId}:${label}`);
}
return getWorkerBootstrapUrl(result.toString(), `${moduleId}:${label}`);
},
...defaultEnvironment,
};
}
private registerOverrideServices() {
const codeEditorService = this.overrideServicesRegistry.getRegisteredService<AbstractCodeEditorService>(
ServiceNames.CODE_EDITOR_SERVICE,
@ -531,6 +601,37 @@ export class MonacoClientContribution
return false;
}
}
registerStaticResolver(service: StaticResourceService): void {
service.registerStaticResourceProvider({
scheme: Schemes.monaco,
resolveStaticResource: (uri) => {
const path = uri.codeUri.path;
switch (path) {
case 'worker': {
const query = uri.query;
if (query) {
const { moduleId } = JSON.parse(query);
if (moduleId === 'workerMain.js') {
return URI.parse(
getCdnHref(
packageName,
'worker/editor.worker.bundle.js',
packageVersion,
this.appConfig.componentCDNType,
),
);
}
}
break;
}
}
return uri;
},
});
}
}
function transformMonacoMenuItem(item: monacoActions.IMenuItem | monacoActions.ISubmenuItem): IMenuItem | ISubmenuItem {

View File

@ -0,0 +1,37 @@
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const webpack = require('webpack');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
/**
* @type {import('webpack').Configuration}
*/
module.exports = {
mode: process.env.NODE_ENV || 'development',
entry: {
'editor.worker': '@opensumi/monaco-editor-core/esm/vs/editor/editor.worker.js',
},
devtool: process.env.NODE_ENV === 'production' ? false : 'source-map',
output: {
globalObject: 'self',
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'worker'),
clean: true,
publicPath: '',
},
optimization:
process.env.NODE_ENV === 'production'
? {
minimize: true,
minimizer: [new TerserPlugin()],
}
: {},
plugins: [
new WebpackManifestPlugin({}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
],
stats: process.env.CI ? 'errors-only' : 'normal',
};

View File

@ -2020,6 +2020,7 @@ __metadata:
tsx: "npm:^4.7.1"
typescript: "npm:4.9.3"
webpack: "npm:^5.90.0"
webpack-manifest-plugin: "npm:^5.0.0"
languageName: unknown
linkType: soft
@ -18010,7 +18011,7 @@ __metadata:
languageName: node
linkType: hard
"source-list-map@npm:^2.0.0":
"source-list-map@npm:^2.0.0, source-list-map@npm:^2.0.1":
version: 2.0.1
resolution: "source-list-map@npm:2.0.1"
checksum: 10/3918ffba5fe8447bc816800026fe707aab233d9d05a3487225d880e23b7e37ed455b4e1b844e05644f6ecc7c9b837c0cc32da54dd37f77c993370ebcdb049246
@ -19958,6 +19959,18 @@ __metadata:
languageName: node
linkType: hard
"webpack-manifest-plugin@npm:^5.0.0":
version: 5.0.0
resolution: "webpack-manifest-plugin@npm:5.0.0"
dependencies:
tapable: "npm:^2.0.0"
webpack-sources: "npm:^2.2.0"
peerDependencies:
webpack: ^5.47.0
checksum: 10/466ade444c23d4a8ec3d1a108ec2142468cb260570533acf2cf68806065ccdef649dbac0fa6b0700f4c6d2497535ae950a20e83b26edb25ccfa9bb51538fa607
languageName: node
linkType: hard
"webpack-merge@npm:^5.10.0, webpack-merge@npm:^5.7.3":
version: 5.10.0
resolution: "webpack-merge@npm:5.10.0"
@ -19979,6 +19992,16 @@ __metadata:
languageName: node
linkType: hard
"webpack-sources@npm:^2.2.0":
version: 2.3.1
resolution: "webpack-sources@npm:2.3.1"
dependencies:
source-list-map: "npm:^2.0.1"
source-map: "npm:^0.6.1"
checksum: 10/0c4bb91f2899205648da25b68edf4495a360692af2c426cde98b188367478c93d5e33e2b08665e070ac0ece59ade8d52175da656a212b44701ce4a271ca66695
languageName: node
linkType: hard
"webpack-sources@npm:^3.2.3":
version: 3.2.3
resolution: "webpack-sources@npm:3.2.3"