mirror of
https://github.com/go-gitea/gitea.git
synced 2026-01-30 08:10:02 +01:00
1. Upgrade to [jQuery
4.0](https://blog.jquery.com/2026/01/17/jquery-4-0-0/). Two of the
removed APIs are in use by fomantic, but there are [polyfills
present](a3a3e581aa/web_src/fomantic/build/components/dropdown.js (L15-L17))
so it continues to work.
2. Remove manual naming of webpack chunks. I was running into below
webpack error and I see no reason for this manual chunk naming which is
prone to naming collisions. Also, the webpack build now shows all output
assets. This change will result in longer asset filenames, but webpack
should now be able to guarentee that the names are without collisions.
````
ERROR in SplitChunksPlugin
Cache group "defaultVendors" conflicts with existing chunk.
Both have the same name "--------" and existing chunk is not a parent of
the selected modules.
Use a different name for the cache group or make sure that the existing
chunk is a parent (e. g. via dependOn).
HINT: You can omit "name" to automatically create a name.
BREAKING CHANGE: webpack < 5 used to allow to use an entrypoint as
splitChunk. This is no longer allowed when the entrypoint is not a
parent of the selected modules.
Remove this entrypoint and add modules to cache group's 'test' instead.
If you need modules to be evaluated on startup, add them to the existing
entrypoints (make them arrays). See migration guide of more info.
3. Fix test issue related to `p > div` which is invalid as per HTML spec
because `div` is not [phrasing
content](https://html.spec.whatwg.org/multipage/dom.html#phrasing-content-2)
and therefor can not be a descendant of `p`. This is related to
https://github.com/capricorn86/happy-dom/pull/2007.
4. Add webpack globals
5. Remove obsolete docs glob
6. fix security issue for `seroval` package
7. disable [vitest isolate](https://vitest.dev/config/isolate.html) for
30% faster JS tests, which are all pure.
272 lines
8.5 KiB
TypeScript
272 lines
8.5 KiB
TypeScript
import wrapAnsi from 'wrap-ansi';
|
|
import AddAssetPlugin from 'add-asset-webpack-plugin';
|
|
import LicenseCheckerWebpackPlugin from '@techknowlogick/license-checker-webpack-plugin';
|
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
|
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
|
|
import {VueLoaderPlugin} from 'vue-loader';
|
|
import EsBuildLoader from 'esbuild-loader';
|
|
import {parse} from 'node:path';
|
|
import webpack, {type Configuration, type EntryObject} from 'webpack';
|
|
import {fileURLToPath} from 'node:url';
|
|
import {readFileSync, globSync} from 'node:fs';
|
|
import {env} from 'node:process';
|
|
import tailwindcss from 'tailwindcss';
|
|
import tailwindConfig from './tailwind.config.ts';
|
|
|
|
const {EsbuildPlugin} = EsBuildLoader;
|
|
const {SourceMapDevToolPlugin, DefinePlugin, EnvironmentPlugin} = webpack;
|
|
const formatLicenseText = (licenseText: string) => wrapAnsi(licenseText || '', 80).trim();
|
|
|
|
const themes: EntryObject = {};
|
|
for (const path of globSync('web_src/css/themes/*.css', {cwd: import.meta.dirname})) {
|
|
themes[parse(path).name] = [`./${path}`];
|
|
}
|
|
|
|
const isProduction = env.NODE_ENV !== 'development';
|
|
|
|
// ENABLE_SOURCEMAP accepts the following values:
|
|
// true - all enabled, the default in development
|
|
// reduced - minimal sourcemaps, the default in production
|
|
// false - all disabled
|
|
let sourceMaps;
|
|
if ('ENABLE_SOURCEMAP' in env) {
|
|
sourceMaps = ['true', 'false'].includes(env.ENABLE_SOURCEMAP || '') ? env.ENABLE_SOURCEMAP : 'reduced';
|
|
} else {
|
|
sourceMaps = isProduction ? 'reduced' : 'true';
|
|
}
|
|
|
|
// define which web components we use for Vue to not interpret them as Vue components
|
|
const webComponents = new Set([
|
|
// our own, in web_src/js/webcomponents
|
|
'overflow-menu',
|
|
'origin-url',
|
|
'absolute-date',
|
|
// from dependencies
|
|
'markdown-toolbar',
|
|
'relative-time',
|
|
'text-expander',
|
|
]);
|
|
|
|
const filterCssImport = (url: string, ...args: Array<any>) => {
|
|
const cssFile = args[1] || args[0]; // resourcePath is 2nd argument for url and 3rd for import
|
|
const importedFile = url.replace(/[?#].+/, '').toLowerCase();
|
|
|
|
if (cssFile.includes('fomantic')) {
|
|
if (importedFile.includes('brand-icons')) return false;
|
|
if (/(eot|ttf|otf|woff|svg)$/i.test(importedFile)) return false;
|
|
}
|
|
|
|
if (cssFile.includes('katex') && /(ttf|woff)$/i.test(importedFile)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
export default {
|
|
mode: isProduction ? 'production' : 'development',
|
|
entry: {
|
|
index: [
|
|
fileURLToPath(new URL('web_src/js/index.ts', import.meta.url)),
|
|
fileURLToPath(new URL('web_src/fomantic/build/fomantic.css', import.meta.url)),
|
|
fileURLToPath(new URL('web_src/css/index.css', import.meta.url)),
|
|
],
|
|
swagger: [
|
|
fileURLToPath(new URL('web_src/js/standalone/swagger.ts', import.meta.url)),
|
|
fileURLToPath(new URL('web_src/css/standalone/swagger.css', import.meta.url)),
|
|
],
|
|
'external-render-iframe': [
|
|
fileURLToPath(new URL('web_src/js/standalone/external-render-iframe.ts', import.meta.url)),
|
|
fileURLToPath(new URL('web_src/css/standalone/external-render-iframe.css', import.meta.url)),
|
|
],
|
|
'eventsource.sharedworker': [
|
|
fileURLToPath(new URL('web_src/js/features/eventsource.sharedworker.ts', import.meta.url)),
|
|
],
|
|
...(!isProduction && {
|
|
devtest: [
|
|
fileURLToPath(new URL('web_src/js/standalone/devtest.ts', import.meta.url)),
|
|
fileURLToPath(new URL('web_src/css/standalone/devtest.css', import.meta.url)),
|
|
],
|
|
}),
|
|
...themes,
|
|
},
|
|
devtool: false,
|
|
output: {
|
|
path: fileURLToPath(new URL('public/assets', import.meta.url)),
|
|
filename: 'js/[name].js',
|
|
chunkFilename: 'js/[name].[contenthash:8].js',
|
|
},
|
|
optimization: {
|
|
minimize: isProduction,
|
|
minimizer: [
|
|
new EsbuildPlugin({
|
|
target: 'es2020',
|
|
minify: true,
|
|
css: true,
|
|
legalComments: 'none',
|
|
}),
|
|
],
|
|
moduleIds: 'named',
|
|
chunkIds: 'named',
|
|
},
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.vue$/i,
|
|
exclude: /node_modules/,
|
|
loader: 'vue-loader',
|
|
options: {
|
|
compilerOptions: {
|
|
isCustomElement: (tag: string) => webComponents.has(tag),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
test: /\.js$/i,
|
|
exclude: /node_modules/,
|
|
use: [
|
|
{
|
|
loader: 'esbuild-loader',
|
|
options: {
|
|
loader: 'js',
|
|
target: 'es2020',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
test: /\.ts$/i,
|
|
exclude: /node_modules/,
|
|
use: [
|
|
{
|
|
loader: 'esbuild-loader',
|
|
options: {
|
|
loader: 'ts',
|
|
target: 'es2020',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
test: /\.css$/i,
|
|
use: [
|
|
{
|
|
loader: MiniCssExtractPlugin.loader,
|
|
},
|
|
{
|
|
loader: 'css-loader',
|
|
options: {
|
|
sourceMap: sourceMaps === 'true',
|
|
url: {filter: filterCssImport},
|
|
import: {filter: filterCssImport},
|
|
importLoaders: 1,
|
|
},
|
|
},
|
|
{
|
|
loader: 'postcss-loader',
|
|
options: {
|
|
postcssOptions: {
|
|
plugins: [
|
|
tailwindcss(tailwindConfig),
|
|
],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
test: /\.svg$/i,
|
|
include: fileURLToPath(new URL('public/assets/img/svg', import.meta.url)),
|
|
type: 'asset/source',
|
|
},
|
|
{
|
|
test: /\.(ttf|woff2?)$/i,
|
|
type: 'asset/resource',
|
|
generator: {
|
|
filename: 'fonts/[name].[contenthash:8][ext]',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
plugins: [
|
|
new DefinePlugin({
|
|
__VUE_OPTIONS_API__: true, // at the moment, many Vue components still use the Vue Options API
|
|
__VUE_PROD_DEVTOOLS__: false, // do not enable devtools support in production
|
|
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false, // https://github.com/vuejs/vue-cli/pull/7443
|
|
}),
|
|
// all environment variables used in bundled js via process.env must be declared here
|
|
new EnvironmentPlugin({
|
|
TEST: 'false',
|
|
}),
|
|
new VueLoaderPlugin(),
|
|
new MiniCssExtractPlugin({
|
|
filename: 'css/[name].css',
|
|
chunkFilename: 'css/[name].[contenthash:8].css',
|
|
}),
|
|
sourceMaps !== 'false' && new SourceMapDevToolPlugin({
|
|
filename: '[file].[contenthash:8].map',
|
|
...(sourceMaps === 'reduced' && {include: /^js\/index\.js$/}),
|
|
}),
|
|
new MonacoWebpackPlugin({
|
|
filename: 'js/monaco-[name].[contenthash:8].worker.js',
|
|
}),
|
|
isProduction ? new LicenseCheckerWebpackPlugin({
|
|
outputFilename: 'licenses.txt',
|
|
outputWriter: ({dependencies}: {dependencies: Array<Record<string, string>>}) => {
|
|
const line = '-'.repeat(80);
|
|
const goJson = readFileSync('assets/go-licenses.json', 'utf8');
|
|
const goModules = JSON.parse(goJson).map(({name, licenseText}: Record<string, string>) => {
|
|
return {name, body: formatLicenseText(licenseText)};
|
|
});
|
|
const jsModules = dependencies.map(({name, version, licenseName, licenseText}) => {
|
|
return {name, version, licenseName, body: formatLicenseText(licenseText)};
|
|
});
|
|
|
|
const modules = [...goModules, ...jsModules].sort((a, b) => a.name.localeCompare(b.name));
|
|
return modules.map(({name, version, licenseName, body}) => {
|
|
const title = licenseName ? `${name}@${version} - ${licenseName}` : name;
|
|
return `${line}\n${title}\n${line}\n${body}`;
|
|
}).join('\n');
|
|
},
|
|
override: {
|
|
'khroma@*': {licenseName: 'MIT'}, // https://github.com/fabiospampinato/khroma/pull/33
|
|
},
|
|
emitError: true,
|
|
allow: '(Apache-2.0 OR 0BSD OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0 OR Unlicense OR EPL-1.0 OR EPL-2.0)',
|
|
}) : new AddAssetPlugin('licenses.txt', `Licenses are disabled during development`),
|
|
],
|
|
performance: {
|
|
hints: false,
|
|
maxEntrypointSize: Infinity,
|
|
maxAssetSize: Infinity,
|
|
},
|
|
resolve: {
|
|
symlinks: true,
|
|
modules: ['node_modules'],
|
|
},
|
|
watchOptions: {
|
|
ignored: [
|
|
'node_modules/**',
|
|
],
|
|
},
|
|
stats: {
|
|
assetsSort: 'name',
|
|
assetsSpace: Infinity,
|
|
cached: false,
|
|
cachedModules: false,
|
|
children: false,
|
|
chunkModules: false,
|
|
chunkOrigins: false,
|
|
chunksSort: 'name',
|
|
colors: true,
|
|
entrypoints: false,
|
|
groupAssetsByChunk: false,
|
|
groupAssetsByEmitStatus: false,
|
|
groupAssetsByInfo: false,
|
|
groupModulesByAttributes: false,
|
|
modules: false,
|
|
reasons: false,
|
|
runtimeModules: false,
|
|
},
|
|
} satisfies Configuration;
|