diff --git a/.madrun.mjs b/.madrun.mjs
index 0cc7a5ec..391eb946 100644
--- a/.madrun.mjs
+++ b/.madrun.mjs
@@ -16,6 +16,7 @@ const is20 = process.version.startsWith('v2');
// https://stackoverflow.com/a/69746937/4536327
const buildEnv = (is17 || is20) && {
NODE_OPTIONS: '--openssl-legacy-provider',
+ NODE_ENV: 'production',
};
export default {
@@ -56,6 +57,7 @@ export default {
'watch:test:server': async () => `nodemon -w client -w test/client -x ${await run('test:server')}`,
'watch:coverage': async () => [testEnv, `nodemon -w server -w test -w common -x ${await cutEnv('coverage')}`],
'build': async () => run('6to5:*'),
+ 'postbuild': () => 'node .webpack/cp.mjs',
'build:dev': async () => run('build:client:dev'),
'build:client': () => run('6to5:client'),
'build:client:dev': () => run('6to5:client:dev'),
diff --git a/.webpack/cp.mjs b/.webpack/cp.mjs
new file mode 100644
index 00000000..1dacb044
--- /dev/null
+++ b/.webpack/cp.mjs
@@ -0,0 +1,17 @@
+import {cpSync} from 'node:fs';
+
+cpSync('./css/columns', './dist-dev/columns', {
+ recursive: true,
+});
+
+cpSync('./css/themes', './dist-dev/themes', {
+ recursive: true,
+});
+
+cpSync('./css/columns', './dist/columns', {
+ recursive: true,
+});
+
+cpSync('./css/themes', './dist/themes', {
+ recursive: true,
+});
diff --git a/.webpack/css.js b/.webpack/css.js
index e1d6552d..7b4486e1 100644
--- a/.webpack/css.js
+++ b/.webpack/css.js
@@ -1,77 +1,39 @@
'use strict';
-const {env} = require('node:process');
-const fs = require('node:fs');
-const {
- basename,
- extname,
- join,
-} = require('node:path');
+const {env} = require('node:process')
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
+const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isDev = env.NODE_ENV === 'development';
-const extractCSS = (a) => new ExtractTextPlugin(`${a}.css`);
-const extractMain = extractCSS('[name]');
-
-const cssNames = [
- 'nojs',
- 'view',
- 'config',
- 'terminal',
- 'user-menu',
- ...getCSSList('columns'),
- ...getCSSList('themes'),
-];
-
-const cssPlugins = cssNames.map(extractCSS);
const clean = (a) => a.filter(Boolean);
const plugins = clean([
- ...cssPlugins,
- extractMain,
+ new MiniCssExtractPlugin({
+ filename: '[name].css',
+ }),
!isDev && new OptimizeCssAssetsPlugin(),
]);
const rules = [{
- test: /\.css$/,
- exclude: /css\/(nojs|view|config|terminal|user-menu|columns.*|themes.*)\.css/,
- use: extractMain.extract(['css-loader']),
-}, ...cssPlugins.map(extract), {
- test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/,
- use: {
- loader: 'url-loader',
+ test: /\.css$/i,
+ use: [MiniCssExtractPlugin.loader, {
+ loader: "css-loader",
options: {
- limit: 100_000,
+ url: true,
},
- },
-}];
+ }],
+ }, {
+ test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/,
+ type: 'asset/inline',
+}]
+
module.exports = {
plugins,
- module: {
- rules,
- },
+ module: {
+ rules,
+ },
};
-function getCSSList(dir) {
- const base = (a) => basename(a, extname(a));
- const addDir = (name) => `${dir}/${name}`;
- const rootDir = join(__dirname, '..');
-
- return fs
- .readdirSync(`${rootDir}/css/${dir}`)
- .map(base)
- .map(addDir);
-}
-
-function extract(extractPlugin) {
- const {filename} = extractPlugin;
-
- return {
- test: RegExp(`css/${filename}`),
- use: extractPlugin.extract(['css-loader']),
- };
-}
diff --git a/.webpack/js.js b/.webpack/js.js
index d41f9941..1efe48b1 100644
--- a/.webpack/js.js
+++ b/.webpack/js.js
@@ -7,13 +7,17 @@ const {
} = require('node:path');
const {env} = require('node:process');
-const {EnvironmentPlugin} = require('webpack');
+const {
+ EnvironmentPlugin,
+ NormalModuleReplacementPlugin,
+} = require('webpack');
const WebpackBar = require('webpackbar');
-const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
-
const modules = './modules';
const dirModules = './client/modules';
+const dirCss = './css';
+const dirThemes = `${dirCss}/themes`;
+const dirColumns = `${dirCss}/columns`;
const dir = './client';
const {NODE_ENV} = env;
const isDev = NODE_ENV === 'development';
@@ -46,19 +50,43 @@ const rules = clean([
]);
const plugins = [
+ new NormalModuleReplacementPlugin(/^node:/, (resource) => {
+ resource.request = resource.request.replace(/^node:/, '');
+ }),
new EnvironmentPlugin({
NODE_ENV,
}),
- new ServiceWorkerWebpackPlugin({
- entry: join(__dirname, '..', 'client', 'sw', 'sw.js'),
- excludes: ['*'],
- }),
new WebpackBar(),
];
const splitChunks = {
- name: 'cloudcmd.common',
chunks: 'all',
+ cacheGroups: {
+ abcCommon: {
+ name: 'cloudcmd.common',
+ chunks: (chunk) => {
+ const lazyChunks = [
+ 'nojs',
+ 'view',
+ 'edit',
+ 'terminal',
+ 'config',
+ 'user-menu',
+ 'help',
+ 'themes/dark',
+ 'themes/light',
+ 'columns/name-size',
+ 'columns/name-size-date',
+ ];
+
+ return !lazyChunks.includes(chunk.name);
+ },
+ minChunks: 1,
+ enforce: true,
+ priority: -1,
+ reuseExistingChunk: true,
+ },
+ },
};
module.exports = {
@@ -68,12 +96,27 @@ module.exports = {
'node:process': 'process',
'node:path': 'path',
},
+ fallback: {
+ 'path': require.resolve('path-browserify'),
+ 'process': require.resolve('process/browser'),
+ },
},
devtool,
optimization: {
splitChunks,
},
entry: {
+ 'themes/dark': `${dirThemes}/dark.css`,
+ 'themes/light': `${dirThemes}/light.css`,
+ 'columns/name-size': `${dirColumns}/name-size.css`,
+ 'columns/name-size-date': `${dirColumns}/name-size-date.css`,
+ 'nojs': `${dirCss}/nojs.css`,
+ help: `${dirCss}/help.css`,
+ view: `${dirCss}/view.css`,
+ config: `${dirCss}/config.css`,
+ terminal: `${dirCss}/terminal.css`,
+ 'user-menu': `${dirCss}/user-menu.css`,
+ sw: `${dir}/sw/sw.js`,
cloudcmd: `${dir}/cloudcmd.js`,
[`${modules}/edit`]: `${dirModules}/edit.js`,
[`${modules}/edit-file`]: `${dirModules}/edit-file.js`,
diff --git a/client/client.js b/client/client.js
index 4d53c634..ee164763 100644
--- a/client/client.js
+++ b/client/client.js
@@ -138,17 +138,10 @@ function CloudCmdProto(DOM) {
await initModules();
await baseInit();
- await loadStyle();
CloudCmd.route(location.hash);
};
- async function loadStyle() {
- const {prefix} = CloudCmd;
- const name = `${prefix}/dist/cloudcmd.common.css`;
-
- await load.css(name);
- }
this.route = (path) => {
const query = path.split('/');
diff --git a/client/cloudcmd.js b/client/cloudcmd.js
index 47019e55..9703c6b6 100644
--- a/client/cloudcmd.js
+++ b/client/cloudcmd.js
@@ -1,7 +1,7 @@
'use strict';
const process = require('node:process');
-require('./css');
+require('../css/main.css');
const wraptile = require('wraptile');
const load = require('load.js');
diff --git a/client/css.js b/client/css.js
deleted file mode 100644
index e404bf94..00000000
--- a/client/css.js
+++ /dev/null
@@ -1,8 +0,0 @@
-'use strict';
-
-require('../css/main.css');
-require('../css/nojs.css');
-require('../css/columns/name-size-date.css');
-require('../css/columns/name-size.css');
-require('../css/themes/light.css');
-require('../css/themes/dark.css');
diff --git a/client/modules/config/index.js b/client/modules/config/index.js
index 0ec5b100..f8f3e4f3 100644
--- a/client/modules/config/index.js
+++ b/client/modules/config/index.js
@@ -52,12 +52,12 @@ module.exports.init = async () => {
showLoad();
- const {prefix} = CloudCmd;
+ const {DIR_DIST} = CloudCmd;
[Template] = await Promise.all([
Files.get('config-tmpl'),
loadSocket(),
- loadCSS(`${prefix}/dist/config.css`),
+ loadCSS(`${DIR_DIST}/config.css`),
CloudCmd.View(),
]);
diff --git a/css/main.css b/css/main.css
index b30c0ed3..6b901a8e 100644
--- a/css/main.css
+++ b/css/main.css
@@ -1,5 +1,5 @@
-@import url(./urls.css);
@import url(./reset.css);
+@import url(./urls.css);
@import url(./style.css);
@import url(./icons.css);
@import url(./help.css);
diff --git a/html/index.html b/html/index.html
index 0c374b9c..4c4f3ebf 100644
--- a/html/index.html
+++ b/html/index.html
@@ -8,7 +8,7 @@
-
+