ソースを参照

chore: webpack5

richard1015 5 年 前
コミット
3f02c87015
45 ファイル変更915 行追加22 行削除
  1. 1 1
      .gitignore
  2. 9 0
      .postcssrc.js
  3. 91 0
      libs/cli/package.json
  4. 61 0
      libs/cli/src/bin/index.ts
  5. 8 0
      libs/cli/src/commands/build-site.ts
  6. 22 0
      libs/cli/src/commands/build.ts
  7. 11 0
      libs/cli/src/commands/clean.ts
  8. 1 0
      libs/cli/src/commands/commitLint.ts
  9. 1 0
      libs/cli/src/commands/createComponent.ts
  10. 4 0
      libs/cli/src/commands/dev.ts
  11. 1 0
      libs/cli/src/commands/npmPublish.ts
  12. 6 0
      libs/cli/src/commands/test.ts
  13. 5 0
      libs/cli/src/compiler/package.disperse.ts
  14. 5 0
      libs/cli/src/compiler/package.ts
  15. 12 0
      libs/cli/src/compiler/site.ts
  16. 6 0
      libs/cli/src/compiler/test.ts
  17. 87 0
      libs/cli/src/compiler/webpack.ts
  18. 15 0
      libs/cli/src/script/generateIndexScss.ts
  19. 15 0
      libs/cli/src/shims.d.ts
  20. 3 0
      libs/cli/src/test/setup.ts
  21. 6 0
      libs/cli/src/types/types.ts
  22. 14 0
      libs/cli/src/util/dic.ts
  23. 11 0
      libs/cli/src/util/index.ts
  24. 33 0
      libs/cli/src/util/logger.ts
  25. 4 0
      libs/cli/src/vue-shim.d.ts
  26. 166 0
      libs/cli/src/webpack/base.config.ts
  27. 63 0
      libs/cli/src/webpack/dev.config.ts
  28. 42 0
      libs/cli/src/webpack/package.config.ts
  29. 73 0
      libs/cli/src/webpack/package.disperse.config.ts
  30. 39 0
      libs/cli/src/webpack/prod.config.ts
  31. 71 0
      libs/cli/tsconfig.json
  32. 0 0
      libs/md-vue-loader/config.js
  33. 0 0
      libs/md-vue-loader/containers.js
  34. 0 0
      libs/md-vue-loader/fence.js
  35. 0 0
      libs/md-vue-loader/index.js
  36. 0 0
      libs/md-vue-loader/util.js
  37. 19 10
      package.json
  38. 1 1
      src/packages/menuitem/index.vue
  39. 2 2
      src/packages/swiper/demo.vue
  40. 1 1
      src/packages/swiper/index.scss
  41. 1 1
      src/packages/swiper/index.vue
  42. 2 2
      src/sites/doc/components/Search.vue
  43. 1 1
      src/sites/doc/index.html
  44. 0 1
      src/sites/mobile/index.html
  45. 2 2
      vue.config.js

+ 1 - 1
.gitignore

@@ -1,7 +1,7 @@
 .DS_Store
 node_modules
 /dist
-/libs
+/libs/cli/dist_cli
 /jd/upload.js
 yarn.lock
 package-lock.json

+ 9 - 0
.postcssrc.js

@@ -0,0 +1,9 @@
+module.exports = {
+  plugins: {
+    'postcss-import': {},
+    'postcss-url': {},
+    autoprefixer: {
+      overrideBrowserslist: ['last 20 versions']
+    }
+  }
+};

+ 91 - 0
libs/cli/package.json

@@ -0,0 +1,91 @@
+{
+  "name": "@nutui/cli",
+  "version": "3.0.0-beta.0",
+  "description": "nutui cli",
+  "main": "./dist_cli/bin/index.js",
+  "files": [
+    "dist_cli",
+    "README.md",
+    "package.json"
+  ],
+  "npm": {
+    "tag": "next"
+  },
+  "bin": {
+    "nutui-cli": "./dist_cli/bin/index.js"
+  },
+  "engines": {
+    "node": ">=10"
+  },
+  "scripts": {
+    "dev": "tsc --watch --incremental"
+  },
+  "keywords": [
+    "nutuicli"
+  ],
+  "author": "richard1015",
+  "license": "ISC",
+  "peerDependencies": {
+    "vue": "^3.0.0"
+  },
+  "dependencies": {
+    "@babel/cli": "^7.12.17",
+    "@babel/core": "^7.12.17",
+    "@babel/plugin-transform-object-assign": "^7.12.13",
+    "@babel/plugin-transform-runtime": "^7.12.17",
+    "@babel/preset-env": "^7.12.17",
+    "@types/node": "^14.14.31",
+    "address": "^1.1.2",
+    "autoprefixer": "^10.2.4",
+    "babel-loader": "^8.2.2",
+    "commander": "^7.1.0",
+    "copy": "^0.3.2",
+    "copy-webpack-plugin": "^7.0.0",
+    "coveralls": "^3.1.0",
+    "cross-env": "^7.0.3",
+    "css-loader": "^5.0.2",
+    "eslint": "^7.20.0",
+    "eslint-plugin-vue": "^7.6.0",
+    "expect": "26.6.2",
+    "fork-ts-checker-webpack-plugin": "^6.1.0",
+    "fs-extra": "^9.1.0",
+    "highlight.js": "^10.6.0",
+    "html-webpack-plugin": "^5.2.0",
+    "husky": "^5.0.9",
+    "inquirer": "^7.3.3",
+    "jsdom": "16.4.0",
+    "jsdom-global": "3.0.2",
+    "mini-css-extract-plugin": "^1.3.8",
+    "node-sass": "^5.0.0",
+    "nyc": "15.1.0",
+    "optimize-css-assets-webpack-plugin": "^5.0.4",
+    "path": "^0.12.7",
+    "portfinder": "^1.0.28",
+    "postcss-import": "^14.0.0",
+    "postcss-loader": "^5.0.0",
+    "postcss-url": "^10.1.1",
+    "sass-loader": "^11.0.1",
+    "signale": "^1.4.0",
+    "style-loader": "^2.0.0",
+    "stylelint": "^13.10.0",
+    "stylelint-config-standard": "^20.0.0",
+    "stylelint-webpack-plugin": "^2.1.1",
+    "ts-loader": "^8.0.17",
+    "typescript": "^4.1.5",
+    "vue-loader": "^16.1.2",
+    "vue-router": "^4.0.4",
+    "vue-style-loader": "^4.1.2",
+    "@vue/compiler-sfc": "^3.0.5",
+    "webpack": "^5.23.0",
+    "webpack-dev-server": "^3.11.2",
+    "webpack-merge": "^5.7.3",
+    "webpack-node-externals": "2.5.2",
+    "webpackbar": "^5.0.0-3"
+  },
+  "devDependencies": {
+    "@types/copy-webpack-plugin": "^6.4.0",
+    "@types/mini-css-extract-plugin": "^1.2.2",
+    "@types/optimize-css-assets-webpack-plugin": "^5.0.2",
+    "@types/webpack-dev-server": "^3.11.1"
+  }
+}

+ 61 - 0
libs/cli/src/bin/index.ts

@@ -0,0 +1,61 @@
+#!/usr/bin/env node
+import { ROOT_CLI_PATH, ROOT_PACKAGE_PATH } from '../util/dic';
+const config = require(ROOT_PACKAGE_PATH('package.json'));
+import { setNodeEnv } from '../util';
+process.argv[2] === 'dev'
+  ? setNodeEnv('development')
+  : setNodeEnv('production');
+import program from 'commander';
+import { dev } from '../commands/dev';
+import { build } from '../commands/build';
+import { buildSite } from '../commands/build-site';
+import { clean } from '../commands/clean';
+import { createComponent } from '../commands/createComponent';
+import { commitLint } from '../commands/commitLint';
+import { test } from '../commands/test';
+import { release } from '../commands/npmPublish';
+const config_cli = require(ROOT_CLI_PATH('package.json'));
+
+program.version(`@nutui/cli ${config_cli.version}`, '-v', '--version');
+
+program
+  .command('dev')
+  .description('本地调试运行官网和Demo示例')
+  .action(dev);
+
+program
+  .command('build')
+  .description('构建完整版nutui和各个组件可发布到npm的静态资源包')
+  .action(build);
+
+program
+  .command('build-site')
+  .description('构建官网和Demo示例,进行官网发布')
+  .action(buildSite);
+
+program
+  .command('clean')
+  .description('清空打包目录')
+  .action(clean);
+
+program
+  .command('add')
+  .description('新增组件使用该命令')
+  .action(createComponent);
+
+program
+  .command('commit-lint')
+  .description('获取校验commit message 的配置文件')
+  .action(commitLint);
+
+program
+  .command('test')
+  .description('运行单元测试')
+  .action(test);
+
+program
+  .command('release')
+  .description('发布版本...待开发')
+  .action(release);
+
+program.parse(process.argv);

+ 8 - 0
libs/cli/src/commands/build-site.ts

@@ -0,0 +1,8 @@
+import { emptyDir } from 'fs-extra';
+import { compileSite } from '../compiler/site';
+import { DIST_DIR } from '../util/dic';
+export async function buildSite() {
+  await emptyDir(DIST_DIR);
+  await compileSite(true);
+  process.exit();
+}

+ 22 - 0
libs/cli/src/commands/build.ts

@@ -0,0 +1,22 @@
+import { emptyDir } from 'fs-extra';
+import { compilePackage } from '../compiler/package';
+import { DIST_DIR } from '../util/dic';
+import logger from '../util/logger';
+import { compilePackageDisperse } from '../compiler/package.disperse';
+import generateIndexScss from '../script/generateIndexScss';
+export async function build() {
+  try {
+    await emptyDir(DIST_DIR);
+    await generateIndexScss();
+    logger.success('generate nutui.scss success!');
+    await compilePackage(false);
+    logger.success(`build compilePackage false package success!`);
+    await compilePackage(true);
+    logger.success(`build compilePackage true package success!`);
+    await compilePackageDisperse();
+    logger.success(`build compilePackageDisperse package success!`);
+    process.exit();
+  } catch (error) {
+    logger.error(error);
+  }
+}

+ 11 - 0
libs/cli/src/commands/clean.ts

@@ -0,0 +1,11 @@
+import { emptyDir } from 'fs-extra';
+import { DIST_DIR, CACHE_DIR } from '../util/dic';
+import logger from '../util/logger';
+
+export async function clean() {
+  await emptyDir(DIST_DIR);
+  logger.success(`clean ${DIST_DIR} success!`);
+  await emptyDir(CACHE_DIR);
+  logger.success(`clean ${CACHE_DIR} success!`);
+  process.exit();
+}

+ 1 - 0
libs/cli/src/commands/commitLint.ts

@@ -0,0 +1 @@
+export async function commitLint() {}

+ 1 - 0
libs/cli/src/commands/createComponent.ts

@@ -0,0 +1 @@
+export function createComponent() {}

+ 4 - 0
libs/cli/src/commands/dev.ts

@@ -0,0 +1,4 @@
+import { compileSite } from '../compiler/site';
+export async function dev() {
+  await compileSite();
+}

+ 1 - 0
libs/cli/src/commands/npmPublish.ts

@@ -0,0 +1 @@
+export async function release() {}

+ 6 - 0
libs/cli/src/commands/test.ts

@@ -0,0 +1,6 @@
+import { setNodeEnv } from '../util';
+//import { compileTest } from '../compiler/test';
+export async function test() {
+  setNodeEnv('test');
+  //await compileTest();
+}

+ 5 - 0
libs/cli/src/compiler/package.disperse.ts

@@ -0,0 +1,5 @@
+import { compileWebPack } from './webpack';
+import { packageDisperseConfig } from '../webpack/package.disperse.config';
+export function compilePackageDisperse() {
+  return compileWebPack(packageDisperseConfig());
+}

+ 5 - 0
libs/cli/src/compiler/package.ts

@@ -0,0 +1,5 @@
+import { packageConfig } from '../webpack/package.config';
+import { compileWebPack } from './webpack';
+export function compilePackage(isMinimize: boolean) {
+  return compileWebPack(packageConfig(isMinimize));
+}

+ 12 - 0
libs/cli/src/compiler/site.ts

@@ -0,0 +1,12 @@
+import { devConfig } from '../webpack/dev.config';
+import { prodConfig } from '../webpack/prod.config';
+import { compileWebPack } from './webpack';
+import logger from '../util/logger';
+export async function compileSite(prod: boolean = false) {
+  try {
+    prod ? await compileWebPack(prodConfig) : compileWebPack(devConfig);
+    prod && logger.success('build site success!');
+  } catch (error) {
+    logger.error(error);
+  }
+}

+ 6 - 0
libs/cli/src/compiler/test.ts

@@ -0,0 +1,6 @@
+//import { testConfig } from '../webpack/test.config';
+import { compileWebPack } from './webpack';
+import Webpack from 'webpack';
+export function compileTest() {
+  //return compileWebPack(testConfig);
+}

+ 87 - 0
libs/cli/src/compiler/webpack.ts

@@ -0,0 +1,87 @@
+import Webpack from 'webpack';
+import WebpackDevServer from 'webpack-dev-server';
+import logger from '../util/logger';
+import { getPort } from 'portfinder';
+import address from 'address';
+
+function devServer(config: Webpack.Configuration) {
+  const compiler = Webpack(config, (err: any, stats) => {
+    if (err || stats?.hasErrors()) {
+      logger.error(stats?.toString());
+    } else {
+      logger.success('webpack compiler');
+    }
+  });
+
+  const devServerOptions: WebpackDevServer.Configuration = {
+    open: true,
+    host: '0.0.0.0',
+    port: 8080,
+    stats: 'errors-only',
+    publicPath: '/',
+    disableHostCheck: true,
+    hot: true,
+    hotOnly: true,
+    inline: true,
+    quiet: true,
+    index: 'default.html',
+    overlay: {
+      warnings: true,
+      errors: true
+    }
+  };
+  getPort(
+    {
+      port: devServerOptions.port
+    },
+    (err, port) => {
+      if (err) {
+        console.log(err);
+        return;
+      }
+      devServerOptions.port = port;
+      logger.watch('local:  ', `http://localhost:${port}/`);
+      logger.watch('network:  ', `http://${address.ip()}:${port}/`);
+      // const server = new WebpackDevServer(compiler, devServerOptions);
+      // server.listen(port, devServerOptions.host!, err => {
+      //   if (err) logger.error(err);
+      // });
+    }
+  );
+}
+function build(config: Webpack.Configuration) {
+  return new Promise((resolve, reject) => {
+    Webpack(config, (err: any, stats) => {
+      if (err || stats?.hasErrors()) {
+        // 在这里处理错误
+        if (err) {
+          logger.error(err.stack || err);
+          if (err.details) {
+            logger.error(err.details);
+          }
+          return;
+        }
+        const info = stats?.toJson();
+        if (stats?.hasErrors()) {
+          logger.error(info?.errors);
+        }
+        if (stats?.hasWarnings()) {
+          logger.warn(info?.warnings);
+        }
+        reject(err || stats?.toJson());
+      } else {
+        // 处理完成
+        resolve(true);
+      }
+    });
+  });
+}
+export function compileWebPack(config: Webpack.Configuration) {
+  switch (config.mode) {
+    case 'development':
+      devServer(config);
+      break;
+    case 'production':
+      return build(config);
+  }
+}

+ 15 - 0
libs/cli/src/script/generateIndexScss.ts

@@ -0,0 +1,15 @@
+import { ROOT_PACKAGE_PATH } from '../util/dic';
+const conf ={}|| require(ROOT_PACKAGE_PATH('src/config.json'));
+const fs = require('fs');
+export default async function generateIndexScss() {
+  let content = `$assetsPath:'./assets/';`;
+  content += `\n@import './styles/index.scss';`;
+  conf.packages.map((item: { name: string }) => {
+    const cptName = item.name.toLowerCase();
+    content += `\n@import './packages/${cptName}/${cptName}.scss';`;
+  });
+  const filePath = ROOT_PACKAGE_PATH('dist/nutui.scss');
+  fs.writeFile(filePath, content, (err: any) => {
+    if (err) throw err;
+  });
+}

+ 15 - 0
libs/cli/src/shims.d.ts

@@ -0,0 +1,15 @@
+declare module 'signale';
+declare module 'fs-extra';
+declare module 'webpackbar';
+declare module 'html-webpack-plugin';
+
+declare module NodeJS {
+	interface Global {
+		expect: any;
+	}
+}
+
+declare module '*.json' {
+	const value: any;
+	export default value;
+}

+ 3 - 0
libs/cli/src/test/setup.ts

@@ -0,0 +1,3 @@
+require('jsdom-global')();
+window.Date = Date;
+global.expect = require('expect');

+ 6 - 0
libs/cli/src/types/types.ts

@@ -0,0 +1,6 @@
+import type Webpack from 'webpack';
+import type WebpackDevServer from 'webpack-dev-server';
+
+export type WebpackConfig = Webpack.Configuration & {
+  devServer?: WebpackDevServer.Configuration;
+};

+ 14 - 0
libs/cli/src/util/dic.ts

@@ -0,0 +1,14 @@
+import { join, resolve } from 'path';
+
+// cli 目录
+export const ROOT_CLI_PATH = function(dir: string) {
+  return resolve(__dirname, '../../', dir);
+};
+// nutui src 目录
+export const ROOT_PACKAGE_PATH = function(dir: string) {
+  return resolve(__dirname, '../../../../', dir);
+};
+// build dist 目录
+export const DIST_DIR = ROOT_PACKAGE_PATH('dist');
+// markdown cache  目录
+export const CACHE_DIR = ROOT_PACKAGE_PATH('cache');

+ 11 - 0
libs/cli/src/util/index.ts

@@ -0,0 +1,11 @@
+export type NodeEnv = 'production' | 'development' | 'test';
+export function setNodeEnv(value: NodeEnv) {
+  process.env.NODE_ENV = value;
+}
+export function isDev() {
+  return process.env.NODE_ENV === 'development';
+}
+
+export function isTest() {
+  return process.env.NODE_ENV === 'test';
+}

+ 33 - 0
libs/cli/src/util/logger.ts

@@ -0,0 +1,33 @@
+import signale from 'signale';
+// signale.success('Operation successful');
+// signale.debug('Hello', 'from', 'L59');
+// signale.pending('Write release notes for %s', '1.2.0');
+// signale.fatal(new Error('Unable to acquire lock'));
+// signale.watch('Recursively watching build directory...');
+// signale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klauscfhq)'});
+
+// 覆盖任何存在于 `package.json` 的配置
+// signale.config({
+//     displayFilename: true,
+//     displayTimestamp: true,
+//     displayDate: false
+// });
+
+const options = {
+  config: {
+    displayTimestamp: true
+  }
+  // types: {
+  //     start: {
+  //         badge: '🚚',
+  //         color: 'green',
+  //         label: 'state'
+  //     },
+  //     info: {
+  //         badge: '**',
+  //         color: 'yellow',
+  //         label: 'info'
+  //     }
+  // }
+};
+export default new signale.Signale(options);

+ 4 - 0
libs/cli/src/vue-shim.d.ts

@@ -0,0 +1,4 @@
+declare module '*.vue' {
+	import Vue from 'vue';
+	export default Vue;
+}

+ 166 - 0
libs/cli/src/webpack/base.config.ts

@@ -0,0 +1,166 @@
+import Webpack from 'webpack';
+import WebpackBar from 'webpackbar';
+import { VueLoaderPlugin } from 'vue-loader';
+import { ROOT_CLI_PATH, ROOT_PACKAGE_PATH } from '../util/dic';
+import { isDev, isTest } from '../util';
+import MiniCssExtractPlugin from 'mini-css-extract-plugin';
+const nutui_config = require(ROOT_PACKAGE_PATH('package.json'));
+const nutui_cli_config = require(ROOT_CLI_PATH('package.json'));
+const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');
+export const baseConfig: Webpack.Configuration = {
+  stats: 'errors-only',
+  output: {
+    publicPath: './' //相对路径
+  },
+  resolve: {
+    extensions: ['.ts', '.js', '.vue', '.json'],
+    alias: {
+      vue: '@vue/runtime-dom',
+      '@': ROOT_PACKAGE_PATH('src')
+  },
+    symlinks: false
+  },
+  module: {
+    rules: [
+      {
+        test: /\.(sa|sc|c)ss$/,
+        use: [
+          isDev()
+            ? 'style-loader'
+            : {
+                loader: MiniCssExtractPlugin.loader,
+                options: {
+                  publicPath: '../'
+                }
+              },
+          'css-loader',
+          'postcss-loader',
+          {
+            loader: 'sass-loader',
+            options: {
+              additionalData: `@import "~@/styles/variables.scss";@import "~@/sites/assets/styles/variables.scss";`
+            }
+          }
+        ]
+      },
+      {
+        test: /\.(png|jpe?g|gif|webp)$/,
+        loader: 'url-loader',
+        include: [ROOT_PACKAGE_PATH('src')],
+        options: {
+          limit: 3000,
+          name: 'img/[name].[ext]',
+          esModule: false // 否则加载时为 [object]
+        }
+      },
+      {
+        test: /\.(svg)(\?.*)?$/,
+        loader: 'file-loader',
+        options: {
+          esModule: false
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
+        loader: 'url-loader'
+      },
+      {
+        test: /\.md$/,
+        include: [ROOT_PACKAGE_PATH('src')],
+        use: [
+          {
+            loader: 'vue-loader',
+            options: {
+              compilerOptions: {
+                preserveWhitespace: false
+              },
+              loaders: {
+                sass: [
+                  'style-loader',
+                  'css-loader',
+                  'postcss-loader',
+                  'sass-loader'
+                ]
+              }
+            }
+          },
+          {
+            loader: ROOT_CLI_PATH('../md-vue-loader/index.js')
+          }
+        ]
+      },
+      {
+        test: /\.vue$/,
+        include: [ROOT_PACKAGE_PATH('src')],
+        use: [
+          {
+            loader: 'vue-loader',
+            options: {
+              compilerOptions: {
+                preserveWhitespace: false
+              },
+              loaders: {
+                sass: [
+                  'style-loader',
+                  'css-loader',
+                  'postcss-loader',
+                  'sass-loader'
+                ]
+              }
+            }
+          }
+        ]
+      },
+      {
+        test: /\.(js|ts)$/,
+        include: [ROOT_PACKAGE_PATH('src')],
+        use: [
+          'babel-loader',
+          {
+            loader: 'ts-loader',
+            options: {
+              appendTsSuffixTo: ['\\.vue$']
+            }
+          }
+        ],
+        exclude: /node_modules\/(?!(@nutui\/cli))/
+      }
+    ]
+  },
+  plugins: [
+    new ForkTsCheckerPlugin({
+      typescript: {
+        extensions: {
+          vue: {
+            enabled: true,
+            compiler: '@vue/compiler-sfc'
+          }
+        }
+      },
+      logger: {
+        issues: {
+          // skip info message
+          log() {},
+          warn(message: string) {
+            console.log('wwwww',message);
+          },
+          error(message: string) {
+            console.log('ccccc',message);
+          }
+        }
+      }
+    }),
+    new Webpack.BannerPlugin({
+      banner: `${nutui_config.name} v${
+        nutui_config.version
+      } - [base], [fullhash], ${new Date()}
+(c) 2018-2021 JDC
+Released under the MIT License.`
+    }),
+    new VueLoaderPlugin(),
+    new WebpackBar({
+      name: `NutUI CLI v${nutui_cli_config.version}`,
+      color: '#fa2c19'
+    })
+  ]
+};

+ 63 - 0
libs/cli/src/webpack/dev.config.ts

@@ -0,0 +1,63 @@
+import Webpack from 'webpack';
+import merge from 'webpack-merge';
+import HtmlWebpackPlugin from 'html-webpack-plugin';
+import { baseConfig } from './base.config';
+import { ROOT_PACKAGE_PATH } from '../util/dic';
+import MiniCssExtractPlugin from 'mini-css-extract-plugin';
+import { isDev } from '../util';
+export const devConfig: Webpack.Configuration = merge(baseConfig, {
+  mode: 'development',
+  entry: {
+    'nutui-mobile': ROOT_PACKAGE_PATH('src/sites/doc/main.ts'),
+    'nutui-doc': ROOT_PACKAGE_PATH('src/sites/mobile/main.ts')
+  },
+  output: {
+    filename: '[name].bundle.js',
+    chunkFilename: '[name].chunk.js'
+  },
+  optimization: {
+    splitChunks: {
+      automaticNameDelimiter: '_',
+      cacheGroups: {
+        chunks: {
+          chunks: 'all',
+          minChunks: 2,
+          minSize: 0,
+          name: 'common_chunks'
+        }
+      }
+    }
+  },
+  plugins: [
+    new MiniCssExtractPlugin({
+      filename: isDev() ? '[name].css' : 'css/[name].[hash].min.css'
+    }),
+    new HtmlWebpackPlugin({
+      title: 'NutUI',
+      template: ROOT_PACKAGE_PATH('src/sites/doc/index.html'),
+      filename: 'index.html',
+      hash: true, //防止缓存
+      inject: true,
+      chunks: ['chunk-vendors', 'common_chunks', 'nutui-doc'],
+      minify: {
+        minifyJS: true,
+        minifyCSS: true,
+        removeAttributeQuotes: true //压缩 去掉引号
+      }
+    }),
+    new HtmlWebpackPlugin({
+      title: 'NutUI',
+      template: ROOT_PACKAGE_PATH('src/sites/mobile/index.html'),
+      filename: 'demo.html',
+      hash: true, //防止缓存
+      inject: true,
+      chunks: ['chunk-vendors', 'common_chunks', 'nutui-mobile'],
+      minify: {
+        minifyJS: true,
+        minifyCSS: true,
+        removeAttributeQuotes: true //压缩 去掉引号
+      }
+    }),
+    new Webpack.HotModuleReplacementPlugin()
+  ]
+});

+ 42 - 0
libs/cli/src/webpack/package.config.ts

@@ -0,0 +1,42 @@
+import Webpack from 'webpack';
+import merge from 'webpack-merge';
+import { ROOT_PACKAGE_PATH } from '../util/dic';
+import { baseConfig } from './base.config';
+import MiniCssExtractPlugin from 'mini-css-extract-plugin';
+import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
+export function packageConfig(isMinimize: boolean) {
+	const _packageConfig: Webpack.Configuration = {
+		mode: 'production',
+		devtool: 'source-map',
+		entry: {
+			nutui: ROOT_PACKAGE_PATH('src/nutui.js'),
+		},
+		output: {
+			path: ROOT_PACKAGE_PATH('dist/'),
+			filename: isMinimize ? '[name].min.js' : '[name].js',
+			library: '[name]',
+			libraryTarget: 'umd',
+			umdNamedDefine: true,
+			// https://stackoverflow.com/questions/49111086/webpack-4-universal-library-target
+			globalObject: `(typeof self !== 'undefined' ? self : this)`,
+		},
+		externals: {
+			vue: {
+				root: 'Vue',
+				commonjs: 'vue',
+				commonjs2: 'vue',
+				amd: 'vue',
+			},
+		},
+		optimization: {
+			minimize: isMinimize,
+		},
+		plugins: [
+			new MiniCssExtractPlugin({
+				filename: isMinimize ? '[name].min.css' : '[name].css',
+			}),
+		],
+	};
+	isMinimize && _packageConfig.plugins?.push(new OptimizeCSSAssetsPlugin());
+	return merge(baseConfig, _packageConfig);
+}

+ 73 - 0
libs/cli/src/webpack/package.disperse.config.ts

@@ -0,0 +1,73 @@
+import Webpack from 'webpack';
+import merge from 'webpack-merge';
+import { ROOT_PACKAGE_PATH } from '../util/dic';
+import { baseConfig } from './base.config';
+import MiniCssExtractPlugin from 'mini-css-extract-plugin';
+import CopyWebpackPlugin from 'copy-webpack-plugin';
+import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
+// const confs = require(ROOT_PACKAGE_PATH('src/config.json'));
+export function packageDisperseConfig() {
+  const entry: any = {};
+//   confs.packages.map((item: any) => {
+//     const cptName: string = item.name.toLowerCase();
+//     entry[cptName] = ROOT_PACKAGE_PATH(`src/packages/${cptName}/index.js`);
+//   });
+
+  const _packageDisperseConfig: Webpack.Configuration = {
+    mode: 'production',
+    devtool: 'source-map',
+    entry,
+    output: {
+      path: ROOT_PACKAGE_PATH('dist/packages/'),
+      filename: '[name]/[name].js',
+      library: '[name]',
+      libraryTarget: 'umd',
+      umdNamedDefine: true,
+      // https://stackoverflow.com/questions/49111086/webpack-4-universal-library-target
+      globalObject: `(typeof self !== 'undefined' ? self : this)`
+    },
+    externals: {
+      vue: {
+        root: 'Vue',
+        commonjs: 'vue',
+        commonjs2: 'vue',
+        amd: 'vue'
+      }
+    },
+    optimization: {
+      minimize: true
+    },
+    plugins: [
+      new MiniCssExtractPlugin({
+        filename: '[name]/[name].css'
+      }),
+      new OptimizeCSSAssetsPlugin(),
+      new CopyWebpackPlugin({
+        patterns: [
+          {
+            from: ROOT_PACKAGE_PATH('src/'),
+            to: ROOT_PACKAGE_PATH('dist/'),
+            globOptions: {
+              ignore: [
+                'demo.vue',
+                'doc.md',
+                'config.json',
+                'nutui.js',
+                '*.spec.js'
+              ]
+            }
+          }
+        ]
+      }),
+      new CopyWebpackPlugin({
+        patterns: [
+          {
+            from: ROOT_PACKAGE_PATH('types/'),
+            to: ROOT_PACKAGE_PATH('dist/types/')
+          }
+        ]
+      })
+    ]
+  };
+  return merge(baseConfig, _packageDisperseConfig);
+}

+ 39 - 0
libs/cli/src/webpack/prod.config.ts

@@ -0,0 +1,39 @@
+import Webpack from 'webpack';
+import merge from 'webpack-merge';
+import { devConfig } from './dev.config';
+import { ROOT_PACKAGE_PATH, ROOT_CLI_PATH } from '../util/dic';
+import CopyWebpackPlugin from 'copy-webpack-plugin';
+import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
+export const prodConfig: Webpack.Configuration = merge(devConfig, {
+  mode: 'production',
+  output: {
+    path: ROOT_PACKAGE_PATH('dist/'),
+    filename: 'js/[name].[hash].bundle.min.js',
+    chunkFilename: 'js/[name].[chunkhash].chunk.min.js'
+  },
+  optimization: {
+    minimize: true,
+    splitChunks: {
+      automaticNameDelimiter: '_'
+    }
+  },
+  plugins: [
+    new OptimizeCSSAssetsPlugin(),
+    new CopyWebpackPlugin({
+      patterns: [
+        {
+          from: ROOT_CLI_PATH('site/demo/asset/img/favicon.ico'),
+          to: ROOT_PACKAGE_PATH('dist/')
+        }
+      ]
+    }),
+    new CopyWebpackPlugin({
+      patterns: [
+        {
+          from: ROOT_CLI_PATH('site/demo/asset/img/pwa_logo.png'),
+          to: ROOT_PACKAGE_PATH('dist/img/')
+        }
+      ]
+    })
+  ]
+});

+ 71 - 0
libs/cli/tsconfig.json

@@ -0,0 +1,71 @@
+{
+  "compilerOptions": {
+    /* Basic Options */
+    // "incremental": true,                   /* Enable incremental compilation */
+    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
+    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
+    // "lib": [],                             /* Specify library files to be included in the compilation. */
+    // "allowJs": true,                       /* Allow javascript files to be compiled. */
+    // "checkJs": true,                       /* Report errors in .js files. */
+    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+    "declaration": true,                      /* Generates corresponding '.d.ts' file. */
+    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
+    "sourceMap": true,                        /* Generates corresponding '.map' file. */
+    // "outFile": "./",                       /* Concatenate and emit output to single file. */
+    "outDir": "./dist_cli",                           /* Redirect output structure to the directory. */
+    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+    // "composite": true,                     /* Enable project compilation */
+    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
+    // "removeComments": true,                /* Do not emit comments to output. */
+    // "noEmit": true,                        /* Do not emit outputs. */
+    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
+    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+    /* Strict Type-Checking Options */
+    "strict": true,                           /* Enable all strict type-checking options. */
+    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,              /* Enable strict null checks. */
+    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
+    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
+    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
+    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */
+
+    /* Additional Checks */
+    // "noUnusedLocals": true,                /* Report errors on unused locals. */
+    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
+    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
+    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
+    /* Module Resolution Options */
+    "moduleResolution": "node",               /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
+    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
+    // "typeRoots": [],                       /* List of folders to include type definitions from. */
+    // "types": [],                           /* Type declaration files to be included in compilation. */
+    "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
+    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
+
+    /* Source Map Options */
+    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
+    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+    /* Experimental Options */
+    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
+    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
+
+    /* Advanced Options */
+    "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
+    "resolveJsonModule": true,
+    "skipLibCheck": true
+  },
+  "include": ["src/**/*"],
+  "exclude": [
+    "node_modules"
+  ]
+}

loader/md-vue/config.js → libs/md-vue-loader/config.js


loader/md-vue/containers.js → libs/md-vue-loader/containers.js


loader/md-vue/fence.js → libs/md-vue-loader/fence.js


loader/md-vue/index.js → libs/md-vue-loader/index.js


loader/md-vue/util.js → libs/md-vue-loader/util.js


+ 19 - 10
package.json

@@ -36,8 +36,9 @@
   ],
   "scripts": {
     "dev": "vue-cli-service serve",
-    "serve": "vue-cli-service serve",
-    "build": "vue-cli-service build",
+    "serve": "node ./libs/cli/dist_cli/bin/index.js dev",
+    "build": "vue-cli-service build  --target lib --name nutui ./src/nutui.ts --mode production",
+    "build:site": "vue-cli-service build",
     "lint": "vue-cli-service lint",
     "upload": "vue-cli-service build && node ./jd/upload.js",
     "add": "node jd/createComponentMode.js"
@@ -46,11 +47,21 @@
     "@types/swiper": "^5.4.1",
     "axios": "^0.21.0",
     "core-js": "^3.6.5",
-    "sass": "^1.27.0",
-    "sass-loader": "^10.0.4",
+    "css-loader": "^5.0.2",
+    "file-loader": "^6.2.0",
+    "node-sass": "^5.0.0",
+    "postcss": "^8.2.6",
+    "postcss-import": "^14.0.0",
+    "postcss-loader": "^5.0.0",
+    "postcss-url": "^10.1.1",
+    "sass": "^1.32.8",
+    "sass-loader": "^11.0.1",
+    "style-loader": "^2.0.0",
     "swiper": "^4.0.2",
-    "vue": "^3.0.0",
-    "vue-router": "^4.0.0-rc.1"
+    "url-loader": "^4.1.1",
+    "vue": "^3.0.5",
+    "vue-loader": "^16.1.2",
+    "vue-router": "^4.0.4"
   },
   "devDependencies": {
     "@commitlint/cli": "^10.0.0",
@@ -62,7 +73,7 @@
     "@vue/cli-plugin-router": "~4.5.8",
     "@vue/cli-plugin-typescript": "~4.5.8",
     "@vue/cli-service": "~4.5.8",
-    "@vue/compiler-sfc": "^3.0.2",
+    "@vue/compiler-sfc": "^3.0.5",
     "@vue/eslint-config-prettier": "^6.0.0",
     "@vue/eslint-config-typescript": "^5.0.2",
     "eslint": "^6.7.2",
@@ -79,9 +90,7 @@
     "markdown-it-container": "^3.0.0",
     "prettier": "^1.19.1",
     "transliteration": "^2.2.0",
-    "typescript": "~3.9.3",
-    "vue-loader": "16.0.0-beta.7",
-    "vue-template-compiler": "^2.6.12"
+    "typescript": "^4.1.5"
   },
   "eslintConfig": {
     "root": true,

+ 1 - 1
src/packages/menuitem/index.vue

@@ -55,7 +55,7 @@ import {
 } from 'vue';
 import { createComponent } from '@/utils/create';
 import { useParent } from '@/utils/useRelation/useParent';
-import { MENU_KEY } from './../menu/index.vue';
+import { MENU_KEY } from '@/packages/menu/index.vue';
 import Icon from '@/packages/icon/index.vue';
 const { create } = createComponent('menu-item');
 

+ 2 - 2
src/packages/swiper/demo.vue

@@ -174,7 +174,7 @@ export default createDemo({
 }
 </style>
 <style>
-.swiper-container /deep/ .swiper-pagination-bullet-active {
+.swiper-container ::v-deep .swiper-pagination-bullet-active {
   background: linear-gradient(
     90deg,
     rgba(250, 32, 12, 1) 0%,
@@ -188,7 +188,7 @@ export default createDemo({
   background: rgba(255, 255, 255, 0.51) !important;
   border-radius: 2px !important;
 }
-.swiper1 /deep/ .swiper-pagination-bullet-active {
+.swiper1 ::v-deep .swiper-pagination-bullet-active {
   background: rgba(255, 255, 255, 1) !important;
 }
 /* demo2 */

+ 1 - 1
src/packages/swiper/index.scss

@@ -3,7 +3,7 @@
   display: block;
 }
 .nutui-swiper {
-  // /deep/ .swiper-pagination-bullet-active {
+  // ::v-deep .swiper-pagination-bullet-active {
   //   opacity: 1;
   //   background: #007aff;
   //   background: linear-gradient(90deg, rgba(250,32,12,1) 0%,rgba(250,32,12,0.65) 100%);

+ 1 - 1
src/packages/swiper/index.vue

@@ -138,7 +138,7 @@ export default create({
     rgba(250, 32, 12, 0.65) 100%
   );
 }
-.swiper-pagination /deep/ .swiper-pagination-bullet-active {
+.swiper-pagination ::v-deep .swiper-pagination-bullet-active {
   width: 10px;
   border-radius: 3px;
 }

+ 2 - 2
src/sites/doc/components/Search.vue

@@ -36,7 +36,7 @@ export default defineComponent({
       searchIndex: 0,
       searchList: [],
       searchVal: '',
-      searchCName: ''
+      searchCurName: ''
     });
     onMounted(() => {
       const files = require.context('@/packages', true, /doc\.md$/);
@@ -65,7 +65,7 @@ export default defineComponent({
           });
           // console.log('rx2', data.searchList.length, data.searchList);
         } else {
-          data.searchCName = '';
+          data.searchCurName = '';
           data.searchIndex = 0;
           data.searchList = [];
         }

+ 1 - 1
src/sites/doc/index.html

@@ -8,7 +8,7 @@
       content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
       name="viewport"
     />
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
+    <link rel="icon" href="favicon.ico" />
     <title><%= htmlWebpackPlugin.options.title %></title>
     <!-- <title>NutUI - 移动端Vue组件库</title> -->
     <script src="https://h5.m.jd.com/babelDiy/Zeus/2846ykuM7PwipD9E2RzMj2BGEQpA/plugin/share.min.js"></script>

+ 0 - 1
src/sites/mobile/index.html

@@ -8,7 +8,6 @@
       content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
       name="viewport"
     />
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
     <title><%= htmlWebpackPlugin.options.title %></title>
     <!-- <title>NutUI - 移动端Vue组件库</title> -->
     <script src="https://h5.m.jd.com/babelDiy/Zeus/2846ykuM7PwipD9E2RzMj2BGEQpA/plugin/share.min.js"></script>

+ 2 - 2
vue.config.js

@@ -84,8 +84,8 @@ module.exports = {
       .use('vue-loader')
       .loader('vue-loader')
       .end()
-      .use(path.resolve(__dirname, './loader/md-vue/index.js'))
-      .loader(path.resolve(__dirname, './loader/md-vue/index.js'))
+      .use(path.resolve(__dirname, './libs/md-vue-loader/index.js'))
+      .loader(path.resolve(__dirname, './libs/md-vue-loader/index.js'))
       .end();
   }
 };