diff --git a/package.json b/package.json index c0f312fee..18f7d89f2 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,9 @@ "autoprefixer": "^10.4.14", "babel-loader": "^9.1.2", "babel-plugin-module-resolver": "^5.0.0", + "circular-dependency-plugin": "^5.2.2", "css-loader": "^6.7.3", + "css-minimizer-webpack-plugin": "^5.0.0", "fork-ts-checker-webpack-plugin": "^8.0.0", "html-webpack-plugin": "^5.5.0", "less": "^4.1.3", @@ -28,6 +30,7 @@ "npm-run-all": "^4.1.5", "optimize-css-assets-webpack-plugin": "^6.0.1", "postcss": "^8.4.21", + "postcss-loader": "^7.1.0", "style-loader": "^3.3.1", "terser-webpack-plugin": "^5.3.7", "typescript": "^4.9.5", @@ -35,7 +38,7 @@ "webpack": "^5.75.0", "webpack-bundle-analyzer": "^4.8.0", "webpack-cli": "^5.0.1", - "circular-dependency-plugin": "^5.2.2", - "webpack-dev-server": "^4.11.1" + "webpack-dev-server": "^4.11.1", + "webpack-merge": "^5.8.0" } } diff --git a/packages/fineui/package.json b/packages/fineui/package.json index 94b754ef1..ec5e045fc 100644 --- a/packages/fineui/package.json +++ b/packages/fineui/package.json @@ -1,6 +1,6 @@ { "name": "@fui/core", - "version": "2.0.20230208163847", + "version": "2.0.20230208163847", "description": "fineui", "main": "dist/fineui_without_conflict.min.js", "module": "dist/es/index.js", @@ -9,6 +9,7 @@ "fui-cli": "./bin/cli/cli.js" }, "sideEffects": [ + "**/*.less", "src/**/*.js", "dist/es/core/*.js", "dist/es/core/element/**/*.js", @@ -19,7 +20,10 @@ ], "scripts": { "dev": "babel src -d dist/es --config-file ./esm.babel.js -w", - "build": "webpack --config=webpack.prod.js" + "build": "webpack --config=webpack/webpack.prod.js", + "webpack:css": "webpack --config=webpack/webpack.css.js --mode production", + "biCss": "cross-env LESS_CONFIG_PATH=lessconfig/bi.lessconfig.json LESS_FILE_NAME=bi npm run webpack:css", + "jsyCss": "cross-env LESS_CONFIG_PATH=lessconfig/jsy.lessconfig.json LESS_FILE_NAME=jsy npm run webpack:css" }, "repository": { "type": "git", @@ -40,7 +44,12 @@ "@juggle/resize-observer": "^3.4.0", "@popperjs/core": "2.11.6", "@types/yargs": "17.0.13", + "glob": "^9.3.4", "jquery": "3.6.3", "yargs": "17.6.2" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "cssnano": "^6.0.0" } } diff --git a/packages/fineui/ui/less/app.less b/packages/fineui/ui/less/app.less new file mode 100644 index 000000000..27e4631e7 --- /dev/null +++ b/packages/fineui/ui/less/app.less @@ -0,0 +1,2 @@ +@import "../../src/less/resource/app.less"; +@import "var.less"; diff --git a/packages/fineui/ui/less/background.less b/packages/fineui/ui/less/background.less new file mode 100644 index 000000000..a6cbde36b --- /dev/null +++ b/packages/fineui/ui/less/background.less @@ -0,0 +1,2 @@ +@import "../../src/less/resource/background.less"; +@import "var.less"; diff --git a/packages/fineui/ui/less/font.less b/packages/fineui/ui/less/font.less new file mode 100644 index 000000000..d7399c46e --- /dev/null +++ b/packages/fineui/ui/less/font.less @@ -0,0 +1,2 @@ +@import "../../src/less/resource/font.less"; +@import "var.less"; diff --git a/packages/fineui/ui/less/icon.less b/packages/fineui/ui/less/icon.less new file mode 100644 index 000000000..8aa44a2ae --- /dev/null +++ b/packages/fineui/ui/less/icon.less @@ -0,0 +1,5 @@ +@import "../../src/less/resource/icon.less"; +@import "var.less"; + + + diff --git a/packages/fineui/ui/less/var.less b/packages/fineui/ui/less/var.less new file mode 100644 index 000000000..c89fa87cc --- /dev/null +++ b/packages/fineui/ui/less/var.less @@ -0,0 +1,5 @@ +@webUrl: 'resources?path=/com/fr/web/ui/'; + +@fontUrl: '@{webUrl}font/'; //图片的基本地址 +@imageUrl: '@{webUrl}images/1x/'; //图片的基本地址 +@image2xUrl: '@{webUrl}images/2x/'; //2倍图片的基本地址 diff --git a/packages/fineui/webpack.prod.js b/packages/fineui/webpack.prod.js deleted file mode 100644 index 5c7cba53d..000000000 --- a/packages/fineui/webpack.prod.js +++ /dev/null @@ -1,91 +0,0 @@ -const webpack = require("webpack"); -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const TerserPlugin = require("terser-webpack-plugin"); -const path = require("path"); -const autoprefixer = require("autoprefixer"); -const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); -const CircularDependencyPlugin = require("circular-dependency-plugin"); -const childProcess = require("child_process"); - -function git(command) { - return childProcess.execSync(`git ${command}`).toString().trim(); -} - -let lessVariables = {}; - -if (process.env.LESS_CONFIG_PATH) { - const lessConfigPath = path.isAbsolute(process.env.LESS_CONFIG_PATH) - ? process.env.LESS_CONFIG_PATH - : path.resolve(__dirname, "lessconfig", process.env.LESS_CONFIG_PATH); - - lessVariables = fs.existsSync(lessConfigPath) ? require(lessConfigPath) || {} : {}; -} - -module.exports = { - mode: "production", - entry: { - "fineui.min": "./src/bundle.js", - }, - output: { - path: path.resolve(__dirname, "dist"), - filename: "[name].js", - }, - devtool: "hidden-source-map", - module: { - rules: [ - { - test: /\.js$/, - exclude: /node_modules/, - use: { - loader: "babel-loader", - }, - }, - { - test: /\.(css|less)$/, - use: [ - MiniCssExtractPlugin.loader, - { - loader: "css-loader", - options: { - url: false, - }, - }, - { - loader: "postcss-loader", - options: { - plugins: [autoprefixer], - }, - }, - { - loader: "less-loader", - options: { - relativeUrls: false, - modifyVars: lessVariables, - }, - }, - ], - }, - ], - }, - resolve: { - extensions: [".js", ".ts"], - alias: { - "@": path.resolve(__dirname, "src"), - }, - }, - plugins: [new CircularDependencyPlugin()], - optimization: { - usedExports: false, - minimize: true, - minimizer: [ - new TerserPlugin({ - include: /\.js$/i, - }), - new webpack.BannerPlugin({ - banner: `time: ${new Date().toLocaleString()}; branch: ${git( - "name-rev --name-only HEAD" - )} commit: ${git("rev-parse HEAD")}`, - }), - ], - }, -}; diff --git a/packages/fineui/webpack/attachments.js b/packages/fineui/webpack/attachments.js new file mode 100644 index 000000000..c46279897 --- /dev/null +++ b/packages/fineui/webpack/attachments.js @@ -0,0 +1,265 @@ +const { sync, uniq } = require("./utils"); + +const fixJs = "./dist/fix/fix.js"; +const fixProxyJs = './dist/fix/fix.proxy.js'; +const fixCompact = "./dist/fix/fix.compact.js"; +const workerCompact = './dist/fix/worker.compact.js'; +const lodashJs = "src/core/1.lodash.js"; +const jqueryJs = "src/core/platform/web/jquery/_jquery.js"; + +const runtimePolyfill = ["core-js/stable"]; + +const basicAttachmentMap = { + polyfill: sync([ + "src/core/0.foundation.js", + "src/polyfill/**/*.js", + ]).concat(runtimePolyfill), + core: sync([ + "src/less/core/**/*.less", + "src/less/theme/**/*.less", + // lodashJs, + // jqueryJs, + // "src/core/**/*.js", + // "src/data/**/*.js", + ]), + // 最基础的控件 + base: sync([ + "src/less/base/**/*.less", + // "src/third/**/*.js", + // "src/base/**/*.js", + ]), + // 实现好的一些基础实例 + case: sync([ + // "src/case/**/*.js", + "src/less/case/**/*.less", + ]), + widget: sync([ + "src/less/widget/**/*.less", + "src/less/component/**/*.less", + // "src/widget/**/*.js", + // "src/component/**/*.js", + ]), + router: sync([ + "src/router/**/*.js", + ]), + core_without_platform: sync([ + "src/core/0.foundation.js", + lodashJs, + "src/core/**/*.js", + "src/data/**/*.js", + ], [ + "src/core/platform/**/*.js", + "src/core/controller/**/*.js", + ]), + core_without_normalize: sync( + ["src/less/core/**/*.less", "src/less/theme/**/*.less"], ["src/less/core/normalize.less", "src/less/core/normalize2.less"] + ), + core_without_conflict: sync([ + "src/less/core/**/*.less", + "src/less/theme/**/*.less", + lodashJs, + "src/core/**/*.js", + "src/data/**/*.js", + ], [ + "src/core/conflict.js", + ]), + resource: sync(["src/less/resource/**/*.less"]), + font: sync(["public/less/font.less"]), + ts: ['./typescript/bundle.ts'], + ui: sync([ + 'ui/less/app.less', + 'ui/less/**/*.less', + 'ui/js/**/*.js', + ]), + config: sync(["demo/version.js", "i18n/i18n.cn.js"]), + utils: sync([ + "src/core/0.foundation.js", + lodashJs, + "src/core/constant/**/*.js", + "src/core/func/**/*.js", + "src/core/2.base.js", + "src/core/3.ob.js", + "src/core/5.inject.js", + "src/core/utils/*.js", + "i18n/i18n.cn.js", + "_mobile/date.i18n.cn.js", + "src/data/**/*.js", + ]), + fix: [fixJs], + fixProxy: [fixProxyJs], + less: sync([ + "src/less/core/**/*.less", + "src/less/theme/**/*.less", + "src/less/base/**/*.less", + "src/less/case/**/*.less", + "src/less/widget/**/*.less", + "src/less/component/**/*.less", + ]), + js_bundle: sync(["src/bundle.js"]) +}; + +const bundle = [].concat( + basicAttachmentMap.polyfill, + basicAttachmentMap.core, + basicAttachmentMap.fix, + basicAttachmentMap.base, + basicAttachmentMap.case, + basicAttachmentMap.widget, + sync(["public/less/app.less", "public/less/**/*.less"]), + [fixCompact, workerCompact], + basicAttachmentMap.router, + sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]), + basicAttachmentMap.ts, +); + +const bundleCss = [].concat( + basicAttachmentMap.less, + sync(["public/less/app.less", "public/less/**/*.less"]), +); + +// const bundleModern = [].concat( +// sync(["src/less/modern.less"]), +// sync(["public/modern/app.less", "public/modern/**/*.less"]), +// ); + +const coreJs = [].concat( + basicAttachmentMap.polyfill, + basicAttachmentMap.core, + basicAttachmentMap.fix, + basicAttachmentMap.base, + basicAttachmentMap.case, + basicAttachmentMap.widget, + ['./dist/fix/fix.compact.js'], + basicAttachmentMap.router, + basicAttachmentMap.ts, +); + +const resource = sync(["private/less/app.less", "private/less/**/*.less"]); + +const config = sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]); + +const bundleWithoutNormalize = [].concat( + basicAttachmentMap.core_without_normalize, + sync([ + "src/less/base/**/*.less", + "src/less/case/**/*.less", + "src/less/widget/**/*.less", + "src/less/component/**/*.less", + "public/less/**/*.less", + // ts的less + ], [ + "public/less/app.less", + ]), +); + +const fineuiWithoutNormalize = [].concat( + basicAttachmentMap.core_without_normalize, + sync([ + "src/less/base/**/*.less", + "src/less/case/**/*.less", + "src/less/widget/**/*.less", + "src/less/component/**/*.less", + 'ui/less/app.less', + 'ui/less/**/*.less', + ]), +); + +const fineui = [].concat( + bundleCss, + basicAttachmentMap.js_bundle, + basicAttachmentMap.ui, + // basicAttachmentMap.ts, +); + +const fineuiWithoutConflict = [].concat( + basicAttachmentMap.polyfill, + basicAttachmentMap.core_without_conflict, + basicAttachmentMap.fix, + basicAttachmentMap.base, + basicAttachmentMap.case, + basicAttachmentMap.widget, + basicAttachmentMap.router, + [fixCompact, workerCompact], + basicAttachmentMap.ui, + basicAttachmentMap.ts, +); + +// const fineuiModern = [].concat( +// sync(["src/less/modern.less"]), +// sync([ +// 'ui/modern/app.less', +// 'ui/modern/**/*.less', +// ]), +// ); + +const fineuiProxy = [].concat( + basicAttachmentMap.polyfill, + basicAttachmentMap.core, + basicAttachmentMap.fixProxy, + basicAttachmentMap.base, + basicAttachmentMap.case, + basicAttachmentMap.widget, + basicAttachmentMap.router, + [fixCompact, workerCompact], + basicAttachmentMap.ui, + basicAttachmentMap.ts, +); + +const fineuiWithoutJqueryAndPolyfillJs = [].concat( + runtimePolyfill, + sync([ + "src/core/0.foundation.js", + lodashJs, + "src/core/**/*.js", + "src/data/**/*.js", + ], [ + "src/core/platform/web/**/*.js", + ]), + basicAttachmentMap.fix, + sync([ + "src/base/**/*.js", + "src/case/**/*.js", + ], [ + "src/base/single/input/file.js", + "src/case/ztree/**/*.js", + ]), + basicAttachmentMap.widget, + sync([fixCompact, workerCompact, "ui/js/**/*.js"]), + basicAttachmentMap.ts, +); + +const demo = [].concat( + basicAttachmentMap.polyfill, + basicAttachmentMap.core, + basicAttachmentMap.fix, + basicAttachmentMap.config, + basicAttachmentMap.base, + basicAttachmentMap.case, + basicAttachmentMap.widget, + basicAttachmentMap.router, + sync(["public/less/app.less", "public/less/**/*.less"]), + [fixCompact, workerCompact], + basicAttachmentMap.ts, + sync(["demo/less/*.less", "demo/less/**/*.less", "demo/app.js", "demo/js/**/*.js", "demo/config.js"]), +); + +module.exports = { + fix: fixJs, + fixProxy: fixProxyJs, + lodash: lodashJs, + font: basicAttachmentMap.font, + bundle: uniq(bundle), + fineuiWithoutNormalize: uniq(fineuiWithoutNormalize), + fineuiWithoutConflict: uniq(fineuiWithoutConflict), + bundleWithoutNormalize: uniq(bundleWithoutNormalize), + fineui: uniq(fineui), + fineuiProxy: uniq(fineuiProxy), + fineuiWithoutJqueryAndPolyfillJs: uniq(fineuiWithoutJqueryAndPolyfillJs), + utils: uniq(basicAttachmentMap.utils), + demo: uniq(demo), + coreWithoutPlatform: uniq(basicAttachmentMap.core_without_platform), + coreJs: uniq(coreJs), + resource: uniq((resource)), + config: uniq(config), + bundleCss: uniq(bundleCss), +}; diff --git a/packages/fineui/webpack/dirs.js b/packages/fineui/webpack/dirs.js new file mode 100644 index 000000000..512645e97 --- /dev/null +++ b/packages/fineui/webpack/dirs.js @@ -0,0 +1,16 @@ +const path = require("path"); +module.exports = { + DEST: path.resolve(__dirname, "../dist"), + NODE_MODULES: path.resolve(__dirname, "../node_modules"), + PRIVATE: path.resolve(__dirname, "../private"), + BABEL_CONFIG: path.resolve(__dirname, "../babel.config.js"), + TYPESCRIPT: path.resolve(__dirname, "../typescript"), + ROUTER: path.resolve(__dirname, "../src/router"), + SRC: path.resolve(__dirname, "../src"), + DEMO: path.resolve(__dirname, "../demo"), + PUBLIC: path.resolve(__dirname, "../public"), + I18N: path.resolve(__dirname, "../i18n"), + UI: path.resolve(__dirname, "../ui"), + MOBILE: path.resolve(__dirname, "../_mobile"), + FIX: path.resolve(__dirname, "../dist/fix"), +}; diff --git a/packages/fineui/webpack/utils.js b/packages/fineui/webpack/utils.js new file mode 100644 index 000000000..7ed3de515 --- /dev/null +++ b/packages/fineui/webpack/utils.js @@ -0,0 +1,24 @@ +const path = require('path'); +const glob = require('glob'); + +// const glob = require('fast-glob'); + +function uniq(names) { + return [...new Set(names)]; +} + +const globalExcludes = [ + "**/*/__test__/*.js", +]; + +function sync(patterns, excludes = []) { + const ignore = globalExcludes.concat(excludes).map(pattern => path.join(__dirname, "../", pattern).replace(/\\/g, '/')); + + return patterns.map(pattern => glob.sync(path.join(__dirname, "../", pattern).replace(/\\/g, '/'), { ignore })).flat(); +} + + +module.exports = { + sync, + uniq, +}; diff --git a/packages/fineui/webpack/webpack.common.js b/packages/fineui/webpack/webpack.common.js new file mode 100644 index 000000000..1c0d242f8 --- /dev/null +++ b/packages/fineui/webpack/webpack.common.js @@ -0,0 +1,90 @@ +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const autoprefixer = require("autoprefixer"); +const path = require("path"); +const fs = require("fs"); +const dirs = require("./dirs"); +const attachments = require("./attachments"); + +let lessVariables = {}; +if (process.env.LESS_CONFIG_PATH) { + const lessConfigPath = path.isAbsolute(process.env.LESS_CONFIG_PATH) + ? process.env.LESS_CONFIG_PATH + : path.resolve(__dirname, "lessconfig", process.env.LESS_CONFIG_PATH); + + lessVariables = fs.existsSync(lessConfigPath) ? require(lessConfigPath) || {} : {}; +} + +module.exports = { + entry: { + fineui: attachments.fineui, + }, + externals: { + lodash: "_", + underscore: "_", + }, + resolve: { + mainFields: ["module", "main"], + extensions: [".js", ".ts"], + alias: { + "@": path.resolve(__dirname, "../src"), + }, + }, + + module: { + rules: [ + { + test: /\.(jsx?|tsx?)$/i, + include: [ + dirs.NODE_MODULES, + dirs.PRIVATE, + dirs.PUBLIC, + dirs.MOBILE, + dirs.DEMO, + dirs.I18N, + dirs.UI, + dirs.FIX, + dirs.TYPESCRIPT, + dirs.SRC, + ], + exclude: /node_modules(\/|\\)core-js/, + use: [ + { + loader: "babel-loader", + options: { + configFile: dirs.BABEL_CONFIG, + }, + }, + ], + }, + { + test: /\.(css|less)$/, + use: [ + MiniCssExtractPlugin.loader, + { + loader: "css-loader", + options: { + url: false, + }, + }, + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [autoprefixer], + }, + }, + }, + { + loader: "less-loader", + options: { + lessOptions: { + relativeUrls: false, + modifyVars: lessVariables, + }, + }, + }, + ], + }, + ], + }, +}; diff --git a/packages/fineui/webpack/webpack.css.js b/packages/fineui/webpack/webpack.css.js new file mode 100644 index 000000000..428c70865 --- /dev/null +++ b/packages/fineui/webpack/webpack.css.js @@ -0,0 +1,11 @@ +const { merge } = require("webpack-merge"); +const prod = require("./webpack.prod.js"); +const attachments = require("./attachments"); +prod.entry = {}; + +module.exports = merge(prod, { + mode: "production", + entry: { + [`${process.env.LESS_FILE_NAME}.min`]: attachments.bundleCss, + }, +}); diff --git a/packages/fineui/webpack/webpack.prod.js b/packages/fineui/webpack/webpack.prod.js new file mode 100644 index 000000000..d42cff8db --- /dev/null +++ b/packages/fineui/webpack/webpack.prod.js @@ -0,0 +1,59 @@ +const webpack = require("webpack"); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const TerserPlugin = require("terser-webpack-plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); +const common = require("./webpack.common.js"); +const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); +const childProcess = require("child_process"); +const { merge } = require("webpack-merge"); +const dirs = require("./dirs"); +const attachments = require("./attachments"); + +function git(command) { + return childProcess.execSync(`git ${command}`).toString().trim(); +} + +module.exports = merge(common, { + mode: "production", + + entry: { + "fineui.min": attachments.fineui + }, + + output: { + path: dirs.DEST, + filename: "[name].js", + }, + + devtool: "hidden-source-map", + + optimization: { + usedExports: false, + minimize: true, + minimizer: [ + new TerserPlugin({ + include: /\.min/, + parallel: true, + terserOptions: { + output: { + comments: false, + }, + }, + }), + new webpack.BannerPlugin({ + banner: `time: ${new Date().toLocaleString()}; branch: ${git( + "name-rev --name-only HEAD" + )} commit: ${git("rev-parse HEAD")}`, + }), + new CssMinimizerPlugin(), + ], + }, + + + plugins: [ + new MiniCssExtractPlugin({ + filename: "[name].css", + }), + new ForkTsCheckerWebpackPlugin({}), + ], +});