mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-01 19:15:52 +01:00
split lowlight languages out of the worker bundle
This commit is contained in:
@@ -20,7 +20,8 @@
|
|||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
"gitdiff-parser": "https://github.com/scm-manager/gitdiff-parser#ed3fe7de73dbb0a06c3e6adbbdf22dbae6e66351"
|
"gitdiff-parser": "https://github.com/scm-manager/gitdiff-parser#ed3fe7de73dbb0a06c3e6adbbdf22dbae6e66351",
|
||||||
|
"lowlight": "1.13.1"
|
||||||
},
|
},
|
||||||
"babel": {
|
"babel": {
|
||||||
"presets": [
|
"presets": [
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ module.exports = {
|
|||||||
transformIgnorePatterns: ["node_modules/(?!(@scm-manager)/)"],
|
transformIgnorePatterns: ["node_modules/(?!(@scm-manager)/)"],
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
"\\.(png|svg|jpg|gif|woff2?|eot|ttf)$": path.join(mockDirectory, "fileMock.js"),
|
"\\.(png|svg|jpg|gif|woff2?|eot|ttf)$": path.join(mockDirectory, "fileMock.js"),
|
||||||
"\\.(css|scss|sass)$": path.join(mockDirectory, "styleMock.js"),
|
"\\.(css|scss|sass)$": path.join(mockDirectory, "styleMock.js")
|
||||||
"\\.worker$": path.join(mockDirectory, "workerMock.js")
|
|
||||||
},
|
},
|
||||||
setupFiles: [path.resolve(__dirname, "src", "setup.js")],
|
setupFiles: [path.resolve(__dirname, "src", "setup.js")],
|
||||||
collectCoverage: true,
|
collectCoverage: true,
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
import registerRequireContextHook from "babel-plugin-require-context-hook/register";
|
import registerRequireContextHook from "babel-plugin-require-context-hook/register";
|
||||||
|
import Worker from "./__mocks__/workerMock";
|
||||||
registerRequireContextHook();
|
registerRequireContextHook();
|
||||||
|
window.Worker = Worker;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
/* eslint-disable no-restricted-globals */
|
|
||||||
// @ts-ignore we have no types for react-diff-view
|
// @ts-ignore we have no types for react-diff-view
|
||||||
import { tokenize } from "react-diff-view";
|
import { tokenize } from "react-diff-view";
|
||||||
import refractor from "./refractorAdapter";
|
import refractor from "./refractorAdapter";
|
||||||
|
|
||||||
|
// the WorkerGlobalScope is assigned to self
|
||||||
|
// see https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/self
|
||||||
|
declare const self: Worker;
|
||||||
|
|
||||||
self.addEventListener("message", ({ data: { id, payload } }) => {
|
self.addEventListener("message", ({ data: { id, payload } }) => {
|
||||||
const { hunks, language } = payload;
|
const { hunks, language } = payload;
|
||||||
const options = {
|
const options = {
|
||||||
@@ -10,20 +13,27 @@ self.addEventListener("message", ({ data: { id, payload } }) => {
|
|||||||
language: language,
|
language: language,
|
||||||
refractor
|
refractor
|
||||||
};
|
};
|
||||||
try {
|
|
||||||
const tokens = tokenize(hunks, options);
|
const doTokenization = (worker: Worker) => {
|
||||||
const payload = {
|
try {
|
||||||
success: true,
|
const tokens = tokenize(hunks, options);
|
||||||
tokens: tokens
|
const payload = {
|
||||||
};
|
success: true,
|
||||||
// @ts-ignore seems to use wrong typing
|
tokens: tokens
|
||||||
self.postMessage({ id, payload });
|
};
|
||||||
} catch (ex) {
|
worker.postMessage({ id, payload });
|
||||||
const payload = {
|
} catch (ex) {
|
||||||
success: false,
|
const payload = {
|
||||||
reason: ex.message
|
success: false,
|
||||||
};
|
reason: ex.message
|
||||||
// @ts-ignore seems to use wrong typing
|
};
|
||||||
self.postMessage({ id, payload });
|
worker.postMessage({ id, payload });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createTokenizer = (worker: Worker) => () => doTokenization(worker);
|
||||||
|
|
||||||
|
if (options.highlight) {
|
||||||
|
refractor.loadLanguage(language, createTokenizer(self));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import React, { FC } from "react";
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
// @ts-ignore we have no typings for react-diff-view
|
// @ts-ignore we have no typings for react-diff-view
|
||||||
import { Diff, useTokenizeWorker } from "react-diff-view";
|
import { Diff, useTokenizeWorker } from "react-diff-view";
|
||||||
// @ts-ignore we use webpack worker-loader to load the web worker
|
|
||||||
import TokenizeWorker from "./Tokenize.worker";
|
|
||||||
import { File } from "./DiffTypes";
|
import { File } from "./DiffTypes";
|
||||||
|
|
||||||
// styling for the diff tokens
|
// styling for the diff tokens
|
||||||
@@ -38,7 +36,7 @@ const DiffView = styled(Diff)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
// WebWorker which creates tokens for syntax highlighting
|
// WebWorker which creates tokens for syntax highlighting
|
||||||
const tokenize = new TokenizeWorker();
|
const tokenize = new Worker("./Tokenize.worker.ts", { name: "tokenizer", type: "module" });
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
file: File;
|
file: File;
|
||||||
|
|||||||
@@ -1,11 +1,33 @@
|
|||||||
import lowlight from "lowlight";
|
import lowlight from "lowlight/lib/core";
|
||||||
|
|
||||||
// adapter to let lowlight look like refractor
|
// adapter to let lowlight look like refractor
|
||||||
// this is required because react-diff-view does only support refractor,
|
// this is required because react-diff-view does only support refractor,
|
||||||
// but we want same highlighting as in the source code browser.
|
// but we want same highlighting as in the source code browser.
|
||||||
|
|
||||||
|
const isLanguageRegistered = (lang: string) => {
|
||||||
|
// @ts-ignore listLanguages seems unknown to type
|
||||||
|
const registeredLanguages = lowlight.listLanguages();
|
||||||
|
return !!registeredLanguages[lang];
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadLanguage = (lang: string, callback: () => void) => {
|
||||||
|
if (isLanguageRegistered(lang)) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "tokenizer-lowlight-[request]" */
|
||||||
|
`highlight.js/lib/languages/${lang}`
|
||||||
|
).then(loadedLanguage => {
|
||||||
|
lowlight.registerLanguage(lang, loadedLanguage.default);
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const refractorAdapter = {
|
const refractorAdapter = {
|
||||||
...lowlight,
|
...lowlight,
|
||||||
|
isLanguageRegistered,
|
||||||
|
loadLanguage,
|
||||||
highlight: (value: string, language: string) => {
|
highlight: (value: string, language: string) => {
|
||||||
return lowlight.highlight(language, value).value;
|
return lowlight.highlight(language, value).value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ const createNodeMock = (element: any) => {
|
|||||||
querySelector: (selector: string) => {}
|
querySelector: (selector: string) => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
initStoryshots({
|
initStoryshots({
|
||||||
@@ -17,6 +16,7 @@ initStoryshots({
|
|||||||
// fix snapshot tests with react-diff-view which uses a ref on tr
|
// fix snapshot tests with react-diff-view which uses a ref on tr
|
||||||
// @see https://github.com/storybookjs/storybook/pull/1090
|
// @see https://github.com/storybookjs/storybook/pull/1090
|
||||||
test: snapshotWithOptions({
|
test: snapshotWithOptions({
|
||||||
|
// @ts-ignore types seems not to match
|
||||||
createNodeMock
|
createNodeMock
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.1.3",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.1.3",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
"cache-loader": "^4.1.0",
|
|
||||||
"css-loader": "^3.2.0",
|
"css-loader": "^3.2.0",
|
||||||
"file-loader": "^4.2.0",
|
"file-loader": "^4.2.0",
|
||||||
"mini-css-extract-plugin": "^0.8.0",
|
"mini-css-extract-plugin": "^0.8.0",
|
||||||
@@ -23,11 +22,10 @@
|
|||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
"script-loader": "^0.7.2",
|
"script-loader": "^0.7.2",
|
||||||
"style-loader": "^1.0.0",
|
"style-loader": "^1.0.0",
|
||||||
"thread-loader": "^2.1.3",
|
|
||||||
"worker-loader": "^2.0.0",
|
|
||||||
"webpack": "^4.41.5",
|
"webpack": "^4.41.5",
|
||||||
"webpack-cli": "^3.3.10",
|
"webpack-cli": "^3.3.10",
|
||||||
"webpack-dev-server": "^3.10.1"
|
"webpack-dev-server": "^3.10.1",
|
||||||
|
"worker-plugin": "^3.2.0"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "@scm-manager/eslint-config",
|
"extends": "@scm-manager/eslint-config",
|
||||||
@@ -37,5 +35,6 @@
|
|||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
}
|
},
|
||||||
|
"devDependencies": {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,28 @@ const createIndexMiddleware = require("./middleware/IndexMiddleware");
|
|||||||
const createContextPathMiddleware = require("./middleware/ContextPathMiddleware");
|
const createContextPathMiddleware = require("./middleware/ContextPathMiddleware");
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||||
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
||||||
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
|
const WorkerPlugin = require("worker-plugin");
|
||||||
|
|
||||||
const isDevelopment = process.env.NODE_ENV === "development";
|
const isDevelopment = process.env.NODE_ENV === "development";
|
||||||
const root = path.resolve(process.cwd(), "scm-ui");
|
const root = path.resolve(process.cwd(), "scm-ui");
|
||||||
|
|
||||||
|
const babelPlugins = [];
|
||||||
|
const webpackPlugins = [new WorkerPlugin()];
|
||||||
|
|
||||||
|
let mode = "production";
|
||||||
|
|
||||||
|
if (isDevelopment) {
|
||||||
|
mode = "development";
|
||||||
|
babelPlugins.push(require.resolve("react-refresh/babel"));
|
||||||
|
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
|
||||||
|
webpackPlugins.push(new ReactRefreshWebpackPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`build ${mode} bundles`);
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
mode: isDevelopment ? "development" : "production",
|
mode,
|
||||||
context: root,
|
context: root,
|
||||||
entry: {
|
entry: {
|
||||||
webapp: [path.resolve(__dirname, "webpack-public-path.js"), "./ui-webapp/src/index.tsx"]
|
webapp: [path.resolve(__dirname, "webpack-public-path.js"), "./ui-webapp/src/index.tsx"]
|
||||||
@@ -30,26 +44,16 @@ module.exports = [
|
|||||||
systemjs: false
|
systemjs: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.worker\.(j|t)s$/,
|
|
||||||
use: { loader: "worker-loader" }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
test: /\.(js|ts|jsx|tsx)$/i,
|
test: /\.(js|ts|jsx|tsx)$/i,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: [
|
use: [
|
||||||
{
|
|
||||||
loader: "cache-loader"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: "thread-loader"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
loader: "babel-loader",
|
loader: "babel-loader",
|
||||||
options: {
|
options: {
|
||||||
cacheDirectory: true,
|
cacheDirectory: true,
|
||||||
presets: ["@scm-manager/babel-preset"],
|
presets: ["@scm-manager/babel-preset"],
|
||||||
plugins: [isDevelopment && require.resolve("react-refresh/babel")].filter(Boolean)
|
plugins: babelPlugins
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -76,7 +80,8 @@ module.exports = [
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: path.join(root, "target", "assets"),
|
path: path.join(root, "target", "assets"),
|
||||||
filename: "[name].bundle.js"
|
filename: "[name].bundle.js",
|
||||||
|
chunkFilename: "[name].bundle.js"
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
contentBase: path.join(root, "ui-webapp", "public"),
|
contentBase: path.join(root, "ui-webapp", "public"),
|
||||||
@@ -98,6 +103,7 @@ module.exports = [
|
|||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
runtimeChunk: "single",
|
runtimeChunk: "single",
|
||||||
|
namedChunks: true,
|
||||||
splitChunks: {
|
splitChunks: {
|
||||||
chunks: "all",
|
chunks: "all",
|
||||||
cacheGroups: {
|
cacheGroups: {
|
||||||
@@ -114,7 +120,7 @@ module.exports = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: [isDevelopment && new ReactRefreshWebpackPlugin()].filter(Boolean)
|
plugins: webpackPlugins
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
context: root,
|
context: root,
|
||||||
|
|||||||
Reference in New Issue
Block a user