# web-ecs-model

## 1、介绍
dmes web端业务模型（ts版）

## 2、发布TS库教程

1. 创建文件夹，文件夹名最好等同于模块名，以本模块为例子，模块名称为：web-ecs-model
```
mkdir web-ecs-model
```
2. 初始化项目
```
yarn init
```
3. 根据上述提示填写项目信息，内容将体现在package.json文件中
```json
"name": "web-ecs-model",
  "version": "0.1.1",
  "description": "DMES·WEB端业务模型(TS版)",
  "main": "dist/index.js",
  "types": "dist/types/index.d.ts",
  "repository": "https://gitee.com/appleyk/web-ecs-model.git",
  "author": "appleyk",
  "license": "MIT",
  "private": false,
  "files": [
    "dist","README.md","package.json"
  ],
  ...
```
4. 安装webpack和webpack-cli工具
```
yarn add webpack webpack-cli @webpack-cli/generators -D
```
package.json
```json
...
"devDependencies": {
    "@webpack-cli/generators": "^2.4.2",
    "webpack": "^5.73.0",
    "webpack-cli": "^4.9.2"
  }
```
5. webpacl-cli init 初始化配置
```
yarn webpack-cli init
```
上述弹出的选择依次填写内容如下：
```
? Which of the following JS solutions do you want to use? Typescript
? Do you want to use webpack-dev-server? Yes
? Do you want to simplify the creation of HTML files for your bundle? Yes
? Do you want to add PWA support? No
? Which of the following CSS solutions do you want to use? none
? Do you like to install prettier to format generated configuration? Yes
? Pick a package manager: yarn
```
初始化后的package.json依赖如下
```json
...
"devDependencies": {
    "@webpack-cli/generators": "^2.4.2",
    "html-webpack-plugin": "^5.5.0",
    "prettier": "^2.6.2",
    "ts-loader": "^9.3.0",
    "typescript": "^4.7.3",
    "webpack": "^5.73.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.9.1"
  },
```
此时项目中多出了一个webpack.config.js和tsconfi.json文件，前者用来打包编译源码，后者主要编译ts类型。

6. 安装babel相关库，主要为了测试用
```
yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react -D
```
新建一个文件命名为.babelrc,内容如下
```json
{
    "presets": [
      [
        //preset-env 也是 Babel 提供的预设插件集之一，它可以将 ES6 转换为 ES5
        "@babel/preset-env",
        {
          "useBuiltIns": "usage",
          "corejs": 3
        }
      ],
      "@babel/preset-react" //babel提供的预设插件之一 转换react jsx
    ]
  }
  
```
7. 安装react相关库，主要为了测试用
```
yarn add react react-dom @types/react @types/react-dom -D
```

8. 安装webpack-merge工具
主要为了将开发和生产环境的webpack中的一些通用配置给抽离出去，其中

./config/webpack.common.js
```javascript
const path = require("path")
// 抽离出开发和生产环境下webpack公共部分
module.exports = {
  resolve:{
    /** 定义import 引用时可以省略的文件后缀 */
    extensions:['.js','.jsx','.tsx','.ts'],
    alias:{
       // 设置路径别名，用 @ 代示部分路径。例如：import X from '@/X.js'
      '@':path.join(__dirname,'../src'),
    }
  },
  module: {
    rules: [
      {
        /** 转译jsx */
        test: /\.(ts|tsx)$/,
        loader: "babel-loader",
        exclude: ["/node_modules/"],
      }, 
      {
        /** 转译tsx */
        test: /\.(ts|tsx)$/,
        loader: "ts-loader",
        exclude: ["/node_modules/"],
      },
    ],
  },
};
```

./config/webpack.dev.js
```javascript
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
module.exports=merge(common,{
    mode:"development",
    // 可以追踪源码中 error 的位置
    devtool: "inline-source-map",
    entry:path.join(__dirname, "../public/index.js"),
    output: {
        filename: "bundle.js",
        // 开发模式下不会实际生成 bundle.js 文件，会存放到内存中的。
        path: path.resolve(__dirname, "../public/"), 
      },
      devServer: {
        // 本地服务加载页面所在目录
        static: path.join(__dirname, "../public/"), 
        // 指定启动 ip，localhost 表示本地
        host: "localhost", 
        // 端口号 3000
        port: 3000,
        open: true, 
      },
    plugins: [
      new HtmlWebpackPlugin({
        template: path.resolve(__dirname,"../public/index.html"),
      }),
    ],
    module: {
      rules: [
        {
          test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
          type: "asset",
        },
      ],
    }
})
```
./config/webpack.prod.js
```javascript
const path = require('path')
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
module.exports=merge(common,{
    mode:"production",
    entry: "./src/index.ts",
    output: {
      filename:"index.js",
      path: path.resolve(__dirname, "../dist"),
      // 模式下会清空dist文件夹后再重新编译
      clean:true 
    }
})
```
9. tsconfig.json 最终配置

```json
{
  "compileOnSave": false,
  "compilerOptions": {
    // 打包到的目录
    "outDir": "./dist/types/",
    // 是否生成sourceMap（用于浏览器调试）
    "sourceMap": false,
    // 当一个文件没有默认导出时，允许使用import x from 'y'
    "allowSyntheticDefaultImports": true,
    "noImplicitAny": false,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    // 是否生成声明文件
    "declaration": true,
    // 声明文件打包的位置
    "declarationDir": "./dist/types/",
    // 是否生成声明文件map文件（便于调试）
    "declarationMap": false,
    "moduleResolution": "node",
    "module": "esnext",
    // 转化成的目标语言
    "target": "es5",
    "baseUrl": "./",
    "types": [
      "node"
    ],
    "typeRoots": [
      "./node_modules/@types"
    ],
    "lib": [
      "dom",
      "es2015"
    ],
    "jsx": "react",
    "allowJs": false
  },
  "include": [
    "src/**/*.ts",
    "typings.d.ts", "GxTool.ts",
  ],// 要打包的文件
  "exclude": [
    "node_modules",
    "*.test.ts"
  ]
}
```

10. package.json 打包、编译、推送包配置
package.json
```json
  ...
  "scripts": {
    "start": "webpack serve --config ./config/webpack.dev.js",
    "compile": "webpack --config ./config/webpack.prod.js",
    "build": "tsc",
    "deploy": "npm run build && npm publish --registry https://registry.npmjs.org/"
  }
```
yarn build 会借助tsc目录对src目录进行编译，将ts文件分别转换为对应的*.d.ts和*.js文件，其中前者为ts类型定义文件，主要为了App中引入该模块能够提示类型，后者为ts代码文件编译后的js文件，即干活的。

#### 使用说明
在项目中，直接使用npm 或 yarn 安装就行
```
npm i web-ecs-model or yarn add web-ecs-model
```
例子：
IndexPage.tsx
```javascript
import { FC, ReactElement } from "react";
import { GxUser } from "web-ecs-model";
const userRes= {
	"id": 1433332686733056,
	"name": "appleyk",
	"type": {
		"otid": 1,
		"name": "用户"
	},
	"checkStatus": 1,
	"alias": "管理员",
	"avatar": "4a6ef503fa844639ab210256e19155b8",
	"role": {
		"rid": 3,
		"name": "系统用户",
		"purview": 0
	},
	"uTime": "2022-06-12 12:46:06",
	"cTime": "2021-12-06 13:48:32"
}
const IndexPage:FC = ():ReactElement => {
  const user = new GxUser(userRes);
  return (
    <div className="index-page">
      <h1>用户ID: {user.id},用户昵称: {user.alias}</h1>
    </div>
  );
};
export default IndexPage;
```
效果图：

web-ecs-model模块中GxUser模型定义：  

[![model.png](https://i.postimg.cc/pLgm9PLN/model.png)](https://i.postimg.cc/pLgm9PLN/model.png)


应用中，引入该模块，vscode中ts智能提示:  

[![idea.png](https://i.postimg.cc/ZRsj39BY/idea.png)](https://i.postimg.cc/ZRsj39BY/idea.png)


最终效果:  

[![show.png](https://i.postimg.cc/xjHtqdjQ/show.png)](https://i.postimg.cc/xjHtqdjQ/show.png)
