• 前端项目


    开发环境

    1. nodejs 推荐使用 10.16.0(最新的lts版本)
    2. yarn npm install -g yarn
    3. lerna npm install -g lerna
    4. hzero-front-cli npm install -g hzero-front-cli --registry=http://nexus.saas.hand-china.com/content/groups/hzero-npm-group/

    ide

    1. vscode
    2. webstorm

    创建新项目

    1 创建新项目

    # srm-front 为新项目名称,--puppeteer-skip 为省略非必需的 puppeteer 依赖的下载
    hzero-front-cli srm-front --puppeteer-skip
    

    2 创建主模块

    # 主模块 spfm-front, 项目 srm-front
    cd srm-front
    hzero-front-cli . --create-packages 'spfm-front'
    

    3 创建其他模块

    # 其他模块 spfm-front-sslm
    hzero-front-cli . --create-packages 'spfm-front-sslm'
    

    升级平台依赖

    启动项目

    1. 按需修改 srm-front/config/compileStartEnv.js 中的环境变量
    2. 安装依赖 yarn bootstrap
    3. 编译子模块 lerna run transpile
    4. 打包dll yarn build:dll
    5. 启动本地环境 yarn start

    部署项目

    1. 编译项目:
      1. 安装依赖 yarn bootstrap
      2. 编译子模块 lerna run transpile
      3. 打包dll yarn build:dll
      4. 编译项目 yarn build
    2. 将build完成的dist所有文件 复制到 /usr/share/nginx/html(服务器部署目录)
    3. 替换环境变量
      1. 执行脚本

    run.sh

    /usr/share/nginx/html: 服务器部署目录

    #!/bin/bash
    set -e
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_BASE_PATH $BUILD_BASE_PATH g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_API_HOST $BUILD_API_HOST g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_CLIENT_ID $BUILD_CLIENT_ID g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_BPM_HOST $BUILD_BPM_HOST g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_WFP_EDITOR $BUILD_WFP_EDITOR g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_WEBSOCKET_HOST $BUILD_WEBSOCKET_HOST g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_PLATFORM_VERSION $BUILD_PLATFORM_VERSION g"
    exec "$@"
    

    环境变量说明

      如果`/app/`二级目录部署 需要修改 `srm-front/config/compileBuildEnv.js` 中的 
        BASE_PATH 为 `/app/(二级目录)`
        PUBLIC_URL 为 `/app(二级目录不要后面的/)`
    

    gitlab-ci & docker

    docker/enterpoint.sh

    
    #!/bin/bash
    set -e
    
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_BASE_PATH $BUILD_BASE_PATH g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_API_HOST $BUILD_API_HOST g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_CLIENT_ID $BUILD_CLIENT_ID g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_BPM_HOST $BUILD_BPM_HOST g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_WFP_EDITOR $BUILD_WFP_EDITOR g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_WEBSOCKET_HOST $BUILD_WEBSOCKET_HOST g"
    find /usr/share/nginx/html -name '*.js' | xargs sed -i "s BUILD_PLATFORM_VERSION $BUILD_PLATFORM_VERSION g"
    
    exec "$@"
    

    docker/default.conf

    server {
        listen       80;
        server_name  localhost;
    
        #charset koi8-r;
        #access_log  /var/log/nginx/log/host.access.log  main;
        root   /usr/share/nginx/html;
        
        location / {
          # react-router BrowserHistory 需要配合这个
          try_files $uri /index.html;
        }
    
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    
        # Media: images, icons, video, audio, HTC
        location ~* \.(jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
            expires 1M;
            access_log off;
            add_header Cache-Control "public";
        }
    
        # CSS and Javascript
        location ~* \.(css|js)$ {
            expires 1y;
            access_log off;
            add_header Cache-Control "public";
        }
    }
    

    Dockerfile

    FROM registry.cn-hangzhou.aliyuncs.com/choerodon-tools/frontbase:0.5.0
    
    RUN echo "Asia/shanghai" > /etc/timezone;
    RUN sed -i 's/\#gzip/gzip/g' /etc/nginx/nginx.conf;
    ADD ./dist /usr/share/nginx/html
    ADD ./docker/default.conf /etc/nginx/conf.d/
    COPY ./docker/enterpoint.sh /usr/share/nginx/html
    RUN chmod 777 /usr/share/nginx/html/enterpoint.sh
    ENTRYPOINT ["/usr/share/nginx/html/enterpoint.sh"]
    CMD ["nginx", "-g", "daemon off;"]
    
    EXPOSE 80
    
    

    .gitlab-ci.yml

    # 使用 choerodon 镜像
    image: registry.cn-hangzhou.aliyuncs.com/choerodon-tools/cifront:0.7.0
    
    stages:
      # 编译代码
      - node_build
      # 编译Docker镜像
      - docker_build
    node_build:
      stage: node_build
      script:
        # 安装依赖
        - node_module
        # 编译代码
        - node_build
        # 复制编译好的文件到 磁盘 volumn, 一遍二次构建 获取编译好的文件
        - cp -r dist /cache/${CI_PROJECT_NAME}-${CI_PROJECT_ID}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}/dist
      only:
        # 只在 master 分支merge 的时候触发
        - master
    
    # 打包部署镜像
    docker_build:
      image: registry.cn-hangzhou.aliyuncs.com/choerodon-tools/cibase:0.7.0
      stage: docker_build
      script:
        # 打包镜像
        - docker_build
        # 删除缓存
        - rm -rf /cache/${CI_PROJECT_NAME}-${CI_PROJECT_ID}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
        # 没有找到 估计是 k8s chart 替换环境变量?
        - chart_build
      only:
        - master
    
    .auto_devops: &auto_devops |
      http_status_code=`curl -o .auto_devops.sh -s -m 10 --connect-timeout 10 -w %{http_code} "${CHOERODON_URL}/devops/ci?token=${Token}&type=front"`
      if [ "$http_status_code" != "200" ]; then
        cat .auto_devops.sh
        exit 1
      fi
      source .auto_devops.sh
      function node_module(){
          # 在 volumn 创建缓存目录
          mkdir -p /cache/${CI_PROJECT_NAME}-${CI_PROJECT_ID}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
          # 安装 lerna
          yarn global add lerna
          # 安装依赖
          lerna bootstrap --registry http://nexus.saas.hand-china.com/content/groups/hzero-npm-group
          # 安装依赖
          yarn --registry http://nexus.saas.hand-china.com/content/groups/hzero-npm-group
      }
    
      function node_build(){
          # 可能是有些 脚本需要执行权限
          chmod -R 777 node_modules
          lerna run transpile
          yarn dll
          yarn build
      }
    
      function docker_build(){
          cp -r /cache/${CI_PROJECT_NAME}-${CI_PROJECT_ID}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}/* ${1:-"."}
          docker login -u ${DOCKER_USER} -p ${DOCKER_PWD} ${DOCKER_REGISTRY}
          docker build --pull -t ${DOCKER_REGISTRY}/${GROUP_NAME}/${PROJECT_NAME}:${CI_COMMIT_TAG} ${1:-"."}
          docker push ${DOCKER_REGISTRY}/${GROUP_NAME}/${PROJECT_NAME}:${CI_COMMIT_TAG}
          echo "${DOCKER_REGISTRY}/${GROUP_NAME}/${PROJECT_NAME}:${CI_COMMIT_TAG}"
      }  
    
    before_script:
      - *auto_devops
    

    jenkins & 开发服务器

    jenkins 点击构建后 触发对应 服务器上的 run.sh 脚本

    jenkins-run-sh

    # 获取最新代码
    git pull
    
    # 阻止下载 测试依赖
    export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
    
    # 安装依赖
    yarn install
    
    # 编译子模块
    lerna run transpile
    
    # 打包第三方包等
    yarn build:dll
    
    # 编译
    yarn build
    
    # 编译失败后的处理
    buildErrorCode=$?
    
    if [ 0 -ne $buildErrorCode ]; then
      echo $buildErrorCode
      echo 'build error';
      exit $buildErrorCode;
    fi
    
    # 替换变量
    find dist -name '*.js' | xargs sed -i "s BUILD_API_HOST http://hzeronb.saas.hand-china.com g"
    find dist -name '*.js' | xargs sed -i "s BUILD_CLIENT_ID hzero-front-dev g"
    find dist -name '*.js' | xargs sed -i "s BUILD_WEBSOCKET_HOST ws://hzeronb.saas.hand-china.com/hpfm/websocket g"
    find dist -name '*.js' | xargs sed -i "s BUILD_PLATFORM_VERSION SAAS g"
    find dist -name '*.js' | xargs sed -i "s BUILD_IM_ENABLE true g"
    find dist -name '*.js' | xargs sed -i "s BUILD_IM_WEBSOCKET_HOST ws://192.168.16.150:9876 g"
    find dist -name '*.js' | xargs sed -i "s BUILD_CUSTOMIZE_ICON_NAME customize-icon g"
    
    # 删除 之前的dist目录
    rm -rf html
    mv dist html
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    

    新服务开发流程

    新服务开发分为平台(HZERO)开发和项目开发两种。

    1. 平台开发

    1.1 服务命名

    新服务命名格式为hzero-front-xxx

    新服务需要放在 packags 文件夹下

    packages文件目录

    1.2 配置文件

    配置文件请参照其他hzero-front-xxx模块文件内的配置文件进行配置即可。

    1.3 添加API服务前缀

    先在packages/hzero-front/config/apiConfig.js中,在config中添加新模块的API 比如新模块名为 hzero-front-new

    const config = {
      //...
      // new 模块
      HZERO_NEW: {
        init: () => {
          return "'/new'";
        },
        route: true,
      },
    },
    

    添加过后,使用node命令在根目录下运行packages/hzero-front/scripts/genConfig.js文件。必须运行该文件。

    node ./packages/hzero-front/scripts/genConfig.js
    

    如果有安装run code插件,可以直接右键genConfig.js这个文件后,点击run code即可。

    添加完成后,需要重新编译 hzero-front 模块的文件。在根目录下执行下面的命令,单独编译该模块文件:

    lerna run transpile --scope hzero-front
    

    或者在根目录下执行下面的命令,编译所有文件:

    lerna run transpile
    

    1.4 添加模块路由

    src/utils/getModuleRouters.js文件中添加模块路由,代码格式如下图所示,

    添加对应模块路由

    1.5 代码开发

    详情查看:前端开发指引

    1.6 单模块启动测试

    代码编写完成后,需要单个模块启动测试

    启动方法:在该服务模块文件目录下执行:

    yarn build:dll    // 此行命令只需要在需要第一次启动时执行
    yarn start
    

    1.7 全局启动测试

    hzero-front主体工程依赖于packages下的各模块,所以需要编译packages下的各模块,执行如下命令:

    yarn transpile:prod
    

    或者

    lerna run transpile
    

    接下来,确保dll操作已经执行成功后,执行如下命令,即可启动hzero-front主体工程

    yarn start
    

    1.8 UI使用

    新的功能模块的开发必须要用 Choerodon UI,优先使用Pro版本的组件,Pro版没有的才使用普通版本的组件。

    2. 项目开发

    2.1 服务模块存放位置

    新服务需要放在 packags 文件夹下

    2.2 配置文件

    模块内的配置文件参照其他服务模块文件内的配置文件即可。

    2.3 添加API服务前缀

    先在packages/xxx-front/config/apiConfig.js中,(xxx为项目名)。在config中添加新模块的API 比如新模块名为 demo-new

    const config = {
      //...
      // new 模块
      DEMO_NEW: {
        init: () => {
          return "'/new'";
        },
        route: true,
      },
    },
    

    添加过后,使用node命令在根目录下运行packages/xxx-front/scripts/genConfig.js文件。必须运行该文件。(xxx为项目名)

    node ./packages/xxx-front/scripts/genConfig.js
    

    如果有安装run code插件,可以直接右键genConfig.js这个文件后,点击run code即可。

    运行完这个文件后,packages/xxx-front/src/utils/config.js文件会自动发生变化,无需手动更改。

    添加完成后,需要重新编译 xxx-front 模块的文件,在根路径下执行下面的命令,单独编译该模块文件。

    lerna run transpile --scope xxx-front
    

    或者在根目录下执行下面的命令,编译所有文件:

    lerna run transpile
    

    2.4 添加模块路由

    src/utils/getModuleRouters.js文件中添加模块路由,代码格式如下图所示,(new的位置替换为设置的新服务名,xxx-为项目名)

    // ...
    import * as xxxFrontNewRouters from 'xxx-front-new/lib/utils/router';
    
    export default app =>
      getModuleRouters(app, [
        // ...
        xxxFrontNewRouters,
      ]);
    

    2.5 代码开发

    详情查看:前端开发指引

    2.6 单模块启动测试

    代码编写完成后,需要单个模块启动测试

    启动方法:

    yarn build:dll    // 此行命令只需要在需要第一次启动时执行
    yarn start
    

    2.7 全局启动测试

    hzero-front主体工程依赖于packages下的各模块,所以需要编译packages下的各模块,执行如下命令:

    yarn transpile:prod
    

    或者

    lerna run transpile
    

    接下来,确保dll操作已经执行成功后,执行如下命令,即可启动hzero-front主体工程

    yarn start
    

    2.8 覆盖原有服务

    如果想要覆盖平台原有的服务进行二次开发:

    1.覆盖原有路径(比如想要覆盖汇率类型定义的服务)

    在对应的服务模块下,覆盖原有页面的路由配置

    页面服务路由

    从url上可以发现该页面服务是hpfm服务下的,所以,在packages/xxx-front-hpfm/config/routers.js进行路由覆盖配置

    module.exports = [
      {
        path: "/hpfm/mdm/rate-type",
        component: "RateType",
        models: [
          "rateType",
        ],
      },
    ];
    

    注意:如果只想覆盖某个页面的子页面,那么不仅要覆盖这个子页面的路由,父级页面的路由也必须要进行覆盖。

    2.进行代码开发即可。(如果想要进行二次开发,建议向平台索要该服务的源码进行二次开发)