diff --git a/web/ASC.Web.Editor/webpack/dev/webpack.dev.client.js b/web/ASC.Web.Editor/webpack/dev/webpack.dev.client.js new file mode 100644 index 0000000000..f9f8634579 --- /dev/null +++ b/web/ASC.Web.Editor/webpack/dev/webpack.dev.client.js @@ -0,0 +1,49 @@ +const webpack = require("webpack"); +const { merge } = require("webpack-merge"); +const baseClientConfig = require("../webpack.base.client"); +const path = require("path"); +const { CleanWebpackPlugin } = require("clean-webpack-plugin"); +const pkg = require("../../package.json"); +const homepage = pkg.homepage; + +const clientConfig = { + mode: "development", + entry: { + client: [ + "webpack-hot-middleware/client?reload=true&noInfo=true", + "./src/client/index.js", + ], + }, + output: { + devtoolModuleFilenameTemplate: (info) => + path.resolve(info.absoluteResourcePath).replace(/\\/g, "/"), + }, + devtool: "inline-cheap-module-source-map", + devServer: { + devMiddleware: { + publicPath: homepage, + }, + static: { + directory: path.join(__dirname, "dist/client"), + publicPath: homepage, + }, + port: 5013, + historyApiFallback: { + // Paths with dots should still use the history fallback. + // See https://github.com/facebook/create-react-app/issues/387. + disableDotRule: true, + index: homepage, + }, + hot: true, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", + "Access-Control-Allow-Headers": + "X-Requested-With, content-type, Authorization", + }, + }, + + plugins: [new CleanWebpackPlugin(), new webpack.HotModuleReplacementPlugin()], +}; + +module.exports = merge(baseClientConfig, clientConfig); diff --git a/web/ASC.Web.Editor/webpack/dev/webpack.dev.server.js b/web/ASC.Web.Editor/webpack/dev/webpack.dev.server.js new file mode 100644 index 0000000000..9dbd58aec5 --- /dev/null +++ b/web/ASC.Web.Editor/webpack/dev/webpack.dev.server.js @@ -0,0 +1,13 @@ +const { merge } = require("webpack-merge"); +const baseServerConfig = require("../webpack.base.server"); +const path = require("path"); + +const serverConfig = { + mode: "development", + output: { + devtoolModuleFilenameTemplate: (info) => + path.resolve(info.absoluteResourcePath).replace(/\\/g, "/"), + }, +}; + +module.exports = merge(baseServerConfig, serverConfig); diff --git a/web/ASC.Web.Editor/webpack/prod/webpack.prod.client.js b/web/ASC.Web.Editor/webpack/prod/webpack.prod.client.js new file mode 100644 index 0000000000..19a10a4081 --- /dev/null +++ b/web/ASC.Web.Editor/webpack/prod/webpack.prod.client.js @@ -0,0 +1,16 @@ +const { merge } = require("webpack-merge"); +const TerserPlugin = require("terser-webpack-plugin"); +const baseClientConfig = require("../webpack.base.client"); + +const clientConfig = { + mode: "production", + entry: { client: "./src/client/index.js" }, + devtool: false, + + optimization: { + minimize: true, + minimizer: [new TerserPlugin()], + }, +}; + +module.exports = merge(baseClientConfig, clientConfig); diff --git a/web/ASC.Web.Editor/webpack/prod/webpack.prod.server.js b/web/ASC.Web.Editor/webpack/prod/webpack.prod.server.js new file mode 100644 index 0000000000..fe663c1543 --- /dev/null +++ b/web/ASC.Web.Editor/webpack/prod/webpack.prod.server.js @@ -0,0 +1,8 @@ +const { merge } = require("webpack-merge"); +const baseServerConfig = require("../webpack.base.server"); + +const serverConfig = { + mode: "production", +}; + +module.exports = merge(baseServerConfig, serverConfig); diff --git a/web/ASC.Web.Editor/webpack/webpack.base.client.js b/web/ASC.Web.Editor/webpack/webpack.base.client.js new file mode 100644 index 0000000000..990635e298 --- /dev/null +++ b/web/ASC.Web.Editor/webpack/webpack.base.client.js @@ -0,0 +1,138 @@ +const ModuleFederationPlugin = require("webpack").container + .ModuleFederationPlugin; +const ExternalTemplateRemotesPlugin = require("external-remotes-plugin"); +const CopyPlugin = require("copy-webpack-plugin"); +const AppServerConfig = require("@appserver/common/constants/AppServerConfig"); +const combineUrl = require("@appserver/common/utils/combineUrl"); +const sharedDeps = require("@appserver/common/constants/sharedDependencies"); +const path = require("path"); +const pkg = require("../package.json"); +const LoadablePlugin = require("@loadable/webpack-plugin"); +const commonConfig = require("./webpack.common"); +const { merge } = require("webpack-merge"); +const { proxyURL } = AppServerConfig; +const deps = pkg.dependencies || {}; + +const BUILD_DIR = path.resolve(process.cwd(), "dist"); + +const getDeps = () => { + for (dep in sharedDeps) { + sharedDeps[dep].eager = true; + } + return { + ...deps, + ...sharedDeps, + }; +}; + +const clientBaseConfig = { + target: "web", + + output: { + path: path.resolve(process.cwd(), "dist/client"), + filename: "static/js/[name].[contenthash].bundle.js", + publicPath: "/products/files/doceditor/", + chunkFilename: "static/js/[id].[contenthash].js", + }, + + module: { + rules: [ + { + test: /\.css$/i, + use: ["style-loader", "css-loader"], + }, + { + test: /\.s[ac]ss$/i, + use: [ + // Creates `style` nodes from JS strings + "style-loader", + // Translates CSS into CommonJS + { + loader: "css-loader", + options: { + url: { + filter: (url, resourcePath) => { + // resourcePath - path to css file + + // Don't handle `/static` urls + if (url.startsWith("/static") || url.startsWith("data:")) { + return false; + } + + return true; + }, + }, + }, + }, + // Compiles Sass to CSS + "sass-loader", + ], + }, + ], + }, + resolve: { + extensions: [".jsx", ".js", ".json"], + fallback: { + crypto: false, + }, + }, + performance: { + maxEntrypointSize: 512000, + maxAssetSize: 512000, + }, + plugins: [ + new LoadablePlugin({ + outputAsset: false, + writeToDisk: true, + filename: `${BUILD_DIR}/loadable-stats.json`, + }), + new ModuleFederationPlugin({ + name: "editor", + filename: "remoteEntry.js", + remotes: { + studio: `studio@${combineUrl(proxyURL, "/remoteEntry.js")}`, + files: `files@${combineUrl( + proxyURL, + "/products/files/remoteEntry.js" + )}`, + }, + exposes: { + "./app": "./src/client/index.js", + }, + shared: getDeps(), + }), + new ExternalTemplateRemotesPlugin(), + new CopyPlugin({ + patterns: [ + { + from: "public", + globOptions: { + dot: true, + gitignore: true, + ignore: ["**/index.html"], + }, + }, + ], + }), + ], + + optimization: { + runtimeChunk: "single", // creates a runtime file to be shared for all generated chunks. + splitChunks: { + chunks: "all", // This indicates which chunks will be selected for optimization. + automaticNameDelimiter: "-", + cacheGroups: { + vendor: { + // to convert long vendor generated large name into vendor.js + test: /[\\/]node_modules[\\/]/, + name: "vendor", + chunks: "all", + }, + }, + }, + minimize: false, + minimizer: [], + }, +}; + +module.exports = merge(commonConfig, clientBaseConfig); diff --git a/web/ASC.Web.Editor/webpack/webpack.base.server.js b/web/ASC.Web.Editor/webpack/webpack.base.server.js new file mode 100644 index 0000000000..dce08338fb --- /dev/null +++ b/web/ASC.Web.Editor/webpack/webpack.base.server.js @@ -0,0 +1,24 @@ +const { merge } = require("webpack-merge"); +const commonConfig = require("./webpack.common"); +const path = require("path"); +const nodeExternals = require("webpack-node-externals"); + +const baseServerConfig = { + target: "node", + name: "server", + entry: { server: "./src/index.js" }, + output: { + path: path.resolve(process.cwd(), "dist"), + filename: "server.js", + }, + + // externals: [ + // nodeExternals({ + // modulesDir: path.resolve(__dirname, "../../../node_modules"), + // // allowlist: ["@appserver/common", "@appserver/components"], + // //importType: "module", + // }), + // ], +}; + +module.exports = merge(commonConfig, baseServerConfig); diff --git a/web/ASC.Web.Editor/webpack/webpack.common.js b/web/ASC.Web.Editor/webpack/webpack.common.js new file mode 100644 index 0000000000..20bc836360 --- /dev/null +++ b/web/ASC.Web.Editor/webpack/webpack.common.js @@ -0,0 +1,55 @@ +module.exports = { + resolve: { + extensions: [".js", ".jsx", ".json", ".ts", ".tsx"], + }, + module: { + rules: [ + { + test: /\.(tsx|ts|js|jsx|m?js)$/, + exclude: /node_modules/, + use: [ + { + loader: "babel-loader", + options: { + presets: ["@babel/preset-react", "@babel/preset-env"], + plugins: [ + "@babel/plugin-transform-runtime", + "@babel/plugin-proposal-class-properties", + "@babel/plugin-proposal-export-default-from", + ], + }, + }, + "source-map-loader", + ], + }, + // { + // test: /\.m?js/, + // type: "javascript/auto", + // resolve: { + // fullySpecified: false, + // }, + // }, + // { test: /\.json$/, loader: "json-loader" }, + { + test: /\.react.svg$/, + use: [ + { + loader: "@svgr/webpack", + options: { + svgoConfig: { + plugins: [{ removeViewBox: false }], + }, + }, + }, + ], + }, + { + test: /\.(png|jpe?g|gif|ico)$/i, + type: "asset/resource", + generator: { + filename: "static/images/[hash][ext][query]", + }, + }, + ], + }, +};