• 第一章、web前端架构师


    一、需求分析和架构设计

    1、产品研发流程
    * 公司起步:公司成立、产品雏形(域名、网站、公众号等)、招聘、技术基建
    * 1.0项目启动:kick-off项目启动会、项目计划项目角色
    * 需求:编写需求、评审需求(可能多轮)、UI视觉稿评审
    * 技术方案设计:技术难点调研、技术方案设计、技术方案评审(可能多轮)
    * 开发:写代码包括单元测试、代码走查、合并代码(持续集成)、自测(准入测试)
    * 联调:前后端联调、UI视觉稿确认、产品需求确认
    * 测试:提测、测试、修改bug、测试准出
    * 上线:预览环境上线、预览环境回归测试、线上环境上线、线上环境回归测试
    * 项目总结:项目总结会(总结分析项目的进度、质量、风险、问题等,争取下次项目规避)
    * 年度总结:每个人的年度总结、绩效沟通
    
    2、以架构师的思维分析需求
    * 引导分享:需求分析过程的一个重要步骤,引导用户分享产品,是让业务增长的一种很重要的方式
    * 统计(一周汇总):
        - pv(page访问量)/uv(user访问量)
        - 自定义事件(比如广告飘窗点击事件)
        - 成果转化率 = pv或uv / 自定义事件
    * 分渠道统计:
        - 原理:url?channel=
        - 通过channel来统计哪家广告位所产生的page访问量
    
    3、知识库(语雀)
    * 存放项目团队文档(需求文档、技术方案和技术调研、研发规范细则、测试记录、运维、UI设计)
    * 支持协同编辑
    
    4、架构师的职责
    * 在深入理解业务需求之后,能用软件把业务给模拟出来。并且保证稳定执行,和后续增长。
    * 不一定非得用上看似高大上的技术和框架。技术永远都是为业务服务的。
    
    4、ssr(服务端渲染)
    * toB(面向企业):不适合用
    * toC(面向消费者):适合用,对前端渲染性能有要求
    
    5、单一数据源
    * 一致的、最新的、完整的、无冗余的、可靠的
    * 通过建立产品数据的逻辑联系,将物理上分散的产品数据形成逻辑上的统一整体,为产品数据的
      访问与操作提供唯一的数据源
    
    6、技术方案设计文档
    整体架构设计 V1.0
    * 需求
        - 需求文档链接
    * 范围
        - 整体设计,架构设计,没有细节
    * 模块设计
        - 模块的拆分和关系图,结果
        - 模块的关键功能,职责等
        - 特殊的模块重点说明
            组件库,独立第三方,同时用于编辑器和H5
            自研统计服务,为何自研
    * 作品的数据结构
        - vuex store的结构,解释
        - 数据流转关系图
    * 扩展性保证
        - 扩展组件,数据结构层面
        - 扩展编辑器的功能,例如:组件隐藏、锁定
        - 扩展页面的配置
          (讨论集思广益)
    * 开发提效
        - 脚手架
        - 组件平台
    * 运维保障
        - 线上服务和运维服务
        - 安全
        - 监控和报警
        - 服务扩展性:流量大
    

    二、脚手架架构设计和框架搭建

    1、脚手架简介
    vue create vue-test-app --force -r https://registry.npm.taobao.org
    * 命令的组成
        - 主命令:vue
        - command:create
        - command的param:vue-test-app
        - option:--force可以缩写成-f,-r是--registry的缩写。
          【vue create --help】命令可以查看所有支持的option
        - option的param:为true则可以省略,比如:--force true
    
    2、脚手架的执行原理
    * 在终端输入vue create vue-test-app
    * 终端解析出vue命令
    * 终端在环境变量中找到vue命令
    * 终端根据vue命令链接到实际文件vue.js
    * 终端利用node执行vue.js
    * vue.js解析command/options
    * vue.js执行command
    * 执行完毕,退出执行
    
    3、全局安装@vue/cli的执行原理
    * where和type命令:
        - where vue:查看vue命令所在路径,可以看到两个文件vue(shell脚本文件)
          和vue.cmd(windows内核脚本文件)
        - type vue.cmd:查看vue.cmd脚本文件内容,可以看到实际执行文件
          (环境变量npm目录/node_modules/@vue/cli/bin/vue.js)
    * 【npm i -g @vue/cli】时发生了什么?
        - 下载@vue/cli包
        - 解析package.json({"bin":{"vue":"bin/vue.js"}})
        - 环境变量npm目录下生成vue和vue.cmd文件
    * vue.js第一行【#!/usr/bin/env node】linux环境下作用。
      终端输入./vue.js,相当于执行/usr/bin/env node ./vue.js。
      /usr/bin/env是环境变量,node是命令
    
    4、脚手架开发流程详解
    * 开发流程
        - 创建npm项目
        - 创建脚手架入口文件,最上方添加:#!/usr/bin/env node
        - 配置package.json,添加bin属性
        - 编写脚手架代码
        - 将脚手架发布到npm
    * 使用流程
        - 安装脚手架:npm i -g your-own-cli
        - 使用脚手架:your-own-cli
    * 脚手架开发难点解析
        - 分包:将复杂的系统拆分成若干个模块
        - 命令注册:vue create、vue add、vue invoke
        - 参数解析:vue command [options] <params>
        - options全称:--version、--help
        - options简写:-V、-h
        - 带params的options:--path /desktop/vue-test
        - 帮助文档:
            global help
                usage
                options
                commands
            command help
                usage
                options
        - 其他:
            命令行交互
            日志打印
            命令行文字变色
            网络通信:http/websocket
            文件处理
    
    5、实操入门第一个脚手架
    * 新建linding-cli目录,进入linding-cli目录
    * npm init -y
    * 新建入口文件:/bin/index.js
        - 第一行:#!/usr/bin/env node
    * package.json配置:{"bin":{"linding":"bin/index.js"}}
    * npm login(注意镜像源问题:https://registry.npmjs.org)
    * npm publish(注意包名重复问题)
    * 调试:
        - 远程调试:npm i -g linding-cli
        - 本地调试(linding-cli目录下):npm link
          (linding-cli同级目录npm i -g linding-cli,测试失败)
    * 分包:
        - 本地调试:
            ~ linding-cli目录下:npm link
            ~ linding-cli-lib目录下:npm link(取消:npm unlink)
              (注意package.json入口文件:{"main":"lib/index.js"})
            ~ linding-cli目录下:npm link linding-cli-lib
              (注意不支持es6模块化。取消:npm unlink linding-cli-lib)
            ~ linding-cli的package.json(为了npm publish,需手动添加依赖):
              {"dependencies":{"linding-cli-lib":"^1.0.0"}}
        - 远程调试:
            ~ linding-cli-lib目录下:npm publish
            ~ linding-cli目录下:npm i -S linding-cli-lib
    * 命令注册和参数解析:
        - const argv = require("process").argv:获取命令以空格分隔的字符串数组
    
    6、lerna简介
    * 原生脚手架开发痛点分析
        - 痛点一:重复操作:多peckage本地link、多peckage依赖安装、多peckage单元测试、
          多peckage代码提交、多peckage代码发布
        - 痛点二:版本一致性:发布时版本一致性、发布后相互依赖版本升级
        - package越多,管理复杂度越高
    * lerna简介
        - lerna是一个优化基于git+npm的多peckage项目的管理工具
        - 优势:大幅减少重复操作、提升操作的标准化
        - lerna是架构优化的产物,它揭示了一个架构真理:项目复杂度提升后,就需要对项目进行架构优化,
          架构优化的主要目标往往都是以效能为核心
    * lerna开发脚手架流程
        - 脚手架项目初始化:初始化npm项目、安装lerna、lerna init初始化项目
        - 创建package:lerna create创建package、lerna add安装依赖、lerna link链接依赖
        - 脚手架开发和测试:lerna exec执行shell脚本、lerna run执行npm命令、
          lerna clean清空依赖、lerna bootstrap重装依赖
        - 脚手架发布上线:lerna version bump version、
          lerna changed查看上版本以来的所有变更、lerna diff查看diff、
          lerna publish项目发布
    
    7、实操基于lerna搭建脚手架框架
    * 创建linding-cli目录,进入linding-cli目录
    * npm init -y
    * npm i -D lerna(推荐全局也安装一下)
    * lerna init
        - lerna.json修改{"version":"1.0.0"}
    * lerna create core
        - npm创建组织机构:add organizations、输入组织机构名linding-cli、create、skip
        - package name:(core) @linding-cli/core
        - 其他任意
    * lerna create utils
        - package name:(core) @linding-cli/utils
        - 其他任意
    
    * lerna add @linding-cli/utils packages/core
        - packages/core包安装@linding-cli/utils依赖
        - 不指定包则给所有包安装依赖
    * lerna clean清空依赖
    * lerna bootstrap重装依赖
    * lerna link软链接依赖
        - 前提手动配置好packages/core/package.json
          {"dependencies":{"@linding-cli/utils":"^1.0.0"}}
    
    * lerna exec --scope @linding-cli/utils -- rm -rf node_modules/
        - --scope指定包,不指定则所有包
        - rm -rf是linux命令,windows删除文件我不做测试
    * lerna run --scope @linding-cli/utils test
        - --scope指定包,不指定则所有包
        - test为包中package.json配置的命令(exit 1则会报错)
    
    * 需要关联远程仓库
    * lerna version
    * 所有包的package.json配置{"publishConfig":{"access":"public"}}
    * lerna publish(git远程仓库多一个tag。包下的package-lock.json不提交npm会发布失败)
    
    8、lerna源码阅读
    * core/lerna/package.json找到入口文件core/lerna/cli.js
    * debug configurations添加node.js,
      node parameters输入core/lerna/cli.js ls
    * 调试注意点
        - 安装依赖
        - settings -> node.js and npm -> 
          选中coding assistance for node.js(内置库代码高亮)
        - settings -> stepping -> 取消选中do not step into library scripts
          和do not step into scripts(允许跳转到库文件中去)
    * 断点调试:
        - step over:逐行执行
        - step into:进入方法
        - step out:跳出方法
        - resume program:执行至下一个断点,没有断点则执行结束
    * 项目本地依赖引用方法:
        - {"dependencies":{"@linding-cli/utils":"file:../utils"}}
        - 通过resolveLocalDependencyLinks()方法将本地链接解析成线上链接
        - linding-cli测试:
            ~ 新建入口文件:packages/core/bin/index.js,第一行:#!/usr/bin/env node
            ~ packages/core/package.json配置:{"bin":{"linding":"bin/index.js"}}
            ~ npm link、linding
    * 脚手架command执行过程(lerna源码)
        - core/lerna/cli.js
        - core/lerna/index.js
        - commands/list/command.js(以list为例)
        - commands/list/index.js
        - core/command/index.js
    * 事件循环复习
        - Promise(Fn):js主线程
        - Promise.prototype.then(Fn):微任务队列
    * node在加载模块时向上下文环境注入的5个变量:
        - require、exports、module、__filename、__dirname
    * import-local:
        - 可以优先调用本地lerna命令
    * path.resolve和path.join区别
        - join是路径拼接,resolve相当于cd
    * pkg-dir:
        - 从给定目录开始向上查找,直到找到package.json所在目录并返回
    * Module:
        - Module._nodeModulePaths:生成node_modules可能的路径
        - Module._resolveFilename:解析模块的真实路径
    * Object.create(null):创建的对象没有原型链,节约内存空间
    * "/xxx/yyy".indexOf("/",1):查找第二个"/"的索引
    
    9、yargs快速入门
    #!/usr/bin/env node
    
    // 1、安装:npm i -S yargs
    const yargs = require("yargs/yargs")
    // 2、安装:npm i -S dedent
    const dedent = require("dedent")
    
    /*
    const {hideBin} = require("yargs/helpers")
    const arg = hideBin(process.argv)
    const cli = yargs(arg)*/
    const pkg = require("../package.json")
    const cli = yargs()
    const argv = process.argv.slice(2)
    const context = {
        lindingVersion: pkg.version
    }
    
    cli
        .usage("用法: linding [command] <options>")// 用法提示
        .demandCommand(1, "一个command是必须的. 通过--help查看所有可用的命令和选项")
        .strict()// 未知参数提示
        .recommendCommands()// 最相似命令提示
        .fail((err, msg) => {
            console.log(err, msg)
        })// 信息定制化处理
        .alias("h", "help")// --help别名
        .alias("v", "version")// --version别名
        .alias("r", "registry")// --registry别名
        .wrap(cli.terminalWidth())// 文本显示宽度(命令行宽度)
        .epilogue(dedent`
        当命令执行失败,所有的日志都写在当前工作目录的lerna-debug.log文件中
        更多信息,请查询我们的手册:
        `)// 结尾提示
        .options({
            debug: {
                type: "boolean",
                describe: "启动debug模式",
                alias: "d"
            }
        })// 多个选项
        .option("ci", {
            type: "boolean",
            hidden: true// 定义隐藏选项,一般是内部开发人员使用
        })// 单个选项
        .option("registry", {
            type: "string",
            describe: "定义全局仓库"
        })
        .group(["debug"], "开发选项组")// 选项分组
        .group(["registry"], "其他选项组")
        .command("init [name]", "完成项目初始化", yargs => {
            yargs
                .option("name", {
                    type: "string",
                    describe: "项目的名称",
                    alias: "n"
                })// 【linding init -h】时会显示此选项信息
        }, argv => {
            console.log(argv)// 【linding init】时会打印此参数信息
        })// 命令
        .command({
            command: "list",
            aliases: ["ll", "ls"],// list别名
            describe: "包列表",
            builder(yargs) {
            },
            handler(argv) {
                console.log(argv)
            }
        })
        // .argv
        .parse(argv, context)// argv会拼接context,并注入到脚手架中
    
  • 相关阅读:
    hdu 2211(约瑟夫环问题)
    hdu 3605(二分图的多重匹配 | 网络流)
    hdu 3360(经典二分匹配)
    hdu 2255(KM)
    ajax无翻页刷新简单实例2
    在Updatepanel中使用Response.Redirect
    asp.net 使用UpdatePanel 返回服务器处理后弹出对话框
    再记一个SQL分页存储过程
    DIV中图片垂直居中
    在Repeter中用RadioButton生成单选按钮组的实现
  • 原文地址:https://www.cnblogs.com/linding/p/16311565.html
Copyright © 2020-2023  润新知