https://github.com/react-boilerplate/react-boilerplate
https://github.com/ant-design/ant-design-pro
https://github.com/PanJiaChen/vue-element-admin
https://github.com/kriasoft/react-starter-kit
https://github.com/facebook/create-react-app
https://github.com/senntyou/lila/tree/master/packages/create-lila-app

使用git直接克隆模板

可以直接到模板项目的 github 主页,就能看到整个骨架,比如 react-boilerplateant-design-provue-element-adminreact-starter-kit
以 react-boilerplate 为例:
克隆到本地:

  1. git clone --depth=1 https://github.com/react-boilerplate/react-boilerplate.git <你的项目名字>

切换到目录下:

  1. cd <span class="hljs-tag">&lt;<span class="hljs-name">你的项目名字</span>&gt;</span>

一般来说,接下来运行 npm run install 安装项目的依赖后,就可以运行;有些模板可能有内置的初始化命令,比如 react-boilerplate:

  1. npm run setup

启动应用:

  1. npm start

使用命令行创建

这种方式需要安装相应的命令,然后由命令来创建项目。
以 create-react-app 为例:
安装命令:

  1. npm install -g create-react-app

创建项目:

  1. create-react-app my-app

运行应用:

  1. cd my-app
  2. npm start

自己搭建项目骨架

选择合适的规范来写代码

js 模块化的发展大致有这样一个过程 iife => commonjs/amd => es6,而在这几个规范中:

  • iife: js 原生支持,但一般不会直接使用这种规范写代码
  • amd: requirejs 定义的加载规范,但随着构建工具的出现,便一般不会用这种规范写代码
  • commonjs: node 的模块加载规范,一般会用这种规范写 node 程序
  • es6: ECMAScript2015 定义的模块加载规范,需要转码后浏览器才能运行

这里推荐使用 es6 的模块化规范来写代码,然后用工具转换成 es5 的代码,并且 es6 的代码可以使用 Tree shaking 功能。
参考:

  • IIFE(Immediately-invoked function expression)
  • Tree shaking
  • webpack – tree-shaking
  • webpack 如何优雅的使用tree-shaking(摇树优化)

    选择合适的构建工具

    对于前端项目来说,构建工具一般都选用 webpack,webpack 提供了强大的功能和配置化运行。如果你不喜欢复杂的配置,可以尝试 parcel
    参考:

  • webpack 之外的另一种选择:parcel

    确定是单页面应用(SPA)还是多页面应用

    因为单页面应用与多页面应用在构建的方式上有很大的不同,所以需要从项目一开始就确定,使用哪种模式来构建项目。

    多页面应用

    传统多页面是由后端控制一个 url 对应一个 html 文件,页面之间的跳转需要根据后端给出的 url 跳转到新的 html 上。比如:

    1. http://www.example.com/page1 -> path/to/page1.html
    2. http://www.example.com/page2 -> path/to/page2.html
    3. http://www.example.com/page3 -> path/to/page3.html

    这种方式的应用,项目里会有多个入口文件,搭建项目的时候就需要对这种多入口模式进行封装。另外,也可以选择一些封装的多入口构建工具,如 lila

    单页面应用

    单页面应用(single page application),就是只有一个页面的应用,页面的刷新和内部子页面的跳转完全由 js 来控制。
    一般单页面应用都有以下几个特点:

  • 本地路由,由 js 定义路由、根据路由渲染页面、控制页面的跳转

  • 所有文件只会加载一次,最大限度重用文件,并且极大提升加载速度
  • 按需加载,只有真正使用到页面的时候,才加载相应的文件

这种方式的应用,项目里只有一个入口文件,便无需封装。
参考:

  • 单页面应用(SPA)、按需加载

    选择合适的前端框架与 UI 库

    一般在搭建项目的时候就需要定下前端框架与 UI 库,因为如果后期想更换前端框架和 UI 库,代价是很大的。
    比较现代化的前端框架:

  • react

  • vue
  • angular

一些不错的组合:

  1. 解耦:代码尽量去耦合,这样代码逻辑清晰,也容易扩展
  2. 分块:按照功能对代码进行分块、分组,并能快捷的添加分块、分组
  3. 编辑器友好:需要更新功能时,可以很快的定位到相关文件,并且这些文件应该是很靠近的,而不至于到处找文件

比较推荐的目录结构:

多页面应用

  1. |-- src/ 源代码目录
  2. |-- page1/ page1 页面的工作空间(与这个页面相关的文件都放在这个目录下)
  3. |-- index.html html 入口文件
  4. |-- index.js js 入口文件
  5. |-- index.(css|less|scss) 样式入口文件
  6. |-- html/ html 片段目录
  7. |-- (css|less|scss)/ 样式文件目录
  8. |-- mock/ 本地 json 数据模拟
  9. |-- images/ 图片文件目录
  10. |-- components/ 组件目录(如果基于 react, vue 等组件化框架)
  11. |-- ...
  12. |-- sub-dir/ 子目录
  13. |-- page2/ page2 页面的工作空间(内部结构参考 page1
  14. |-- ...
  15. |-- ...
  16. |-- html/ 公共 html 片段
  17. |-- less/ 公共 less 目录
  18. |-- components/ 公共组件目录
  19. |-- images/ 公共图片目录
  20. |-- mock/ 公共 api-mock 文件目录
  21. |-- ...

单页面应用

  1. |-- src/ 源代码目录
  2. |-- page1/ page1 页面的工作空间
  3. |-- index.js 入口文件
  4. |-- services/ service 目录
  5. |-- models/ model 目录
  6. |-- mock/ 本地 json 数据模拟
  7. |-- images/ 图片文件目录
  8. |-- components/ 组件目录(如果基于 react, vue 等组件化框架)
  9. |-- ...
  10. |-- module1/ 子目录
  11. |-- page2/ page2 页面的工作空间(内部结构参考 page1
  12. |-- ...
  13. |-- images/ 公共图片目录
  14. |-- mock/ 公共 api-mock 文件目录
  15. |-- components/ 公共组件目录
  16. |-- ...

搭建一个好的脚手架

搭建一个好的脚手架,能够更好的编写代码、构建项目等。

  1. |-- / 项目根目录
  2. |-- src/ 源代码目录
  3. |-- package.json npm 项目文件
  4. |-- README.md 项目说明文件
  5. |-- CHANGELOG.md 版本更新记录
  6. |-- .gitignore git 忽略配置文件
  7. |-- .editorconfig 编辑器配置文件
  8. |-- .npmrc npm 配置文件
  9. |-- .npmignore npm 忽略配置文件
  10. |-- .eslintrc eslint 配置文件
  11. |-- .eslintignore eslint 忽略配置文件
  12. |-- .stylelintrc stylelint 配置文件
  13. |-- .stylelintignore stylelint 忽略配置文件
  14. |-- .prettierrc prettier 配置文件
  15. |-- .prettierignore prettier 忽略配置文件
  16. |-- .babelrc babel 配置文件
  17. |-- webpack.config.js webpack 配置文件
  18. |-- rollup.config.js rollup 配置文件
  19. |-- gulpfile.js gulp 配置文件
  20. |-- test/ 测试目录
  21. |-- docs/ 文档目录
  22. |-- jest.config.js jest 配置文件
  23. |-- .gitattributes git 属性配置
  • .``editorconfig: 用这个文件来统一不同编辑器的一些配置,比如 tab 转 2 个空格、自动插入空尾行、去掉行尾的空格等,http://editorconfig.org
  • eslintstylelintprettier: 规范化代码风格、优化代码格式等
  • huskylint-staged: 在 git 提交之前对代码进行审查,否则不予提交
  • .gitlab-ci.yml: gitlab ci 持续集成服务

参考:

到这里为止,一个基本的项目骨架就算搭建好了。

使用版本控制系统管理源代码(git)

项目搭建好后,需要一个版本控制系统来管理源代码。
比较常用的版本管理工具有 gitsvn,现在一般都用 git。
一般开源的项目可以托管到 http://github.com,私人的项目可以托管到 https://gitee.comhttps://coding.net/,而企业的项目则需要自建版本控制系统了。
自建版本控制系统主要有 gitlabgogsgitea:gitlab 是由商业驱动的,比较稳定,社区版是免费的,一般建议选用这个;gogs, gitea 是开源的项目,还不太稳定,期待进一步的更新。
所以,git + gitlab 是不错的配合。

编写代码

编写代码时,js 选用 es6 的模块化规范来写(如果喜欢用 TypeScript,需要加上 ts-loader),样式可以用 lessscss、css 来写。
写 js 模块文件时,注释可以使用 jsdoc 的规范来写,如果配置相应的工具,可以将这些注释导出接口文档。
因为脚手架里有 huskylint-staged 的配合,所以每次提交的代码都会进行代码审查与格式优化,如果不符合规范,则需要把不规范的代码进行修改,然后才能提交到代码仓库中。
比如 console.log(haha.hehe); 这段代码就会遇到错误,不予提交:
这个功能定义在 package.json 中:

  1. {
  2. "devDependencies": { 工具依赖
  3. "babel-eslint": "^8.2.6",
  4. "eslint": "^4.19.1",
  5. "husky": "^0.14.3",
  6. "lint-staged": "^7.2.0",
  7. "prettier": "^1.14.0",
  8. "stylelint": "^9.3.0",
  9. "eslint-config-airbnb": "^17.0.0",
  10. "eslint-config-prettier": "^2.9.0",
  11. "eslint-plugin-babel": "^5.1.0",
  12. "eslint-plugin-import": "^2.13.0",
  13. "eslint-plugin-jsx-a11y": "^6.1.0",
  14. "eslint-plugin-prettier": "^2.6.2",
  15. "eslint-plugin-react": "^7.10.0",
  16. "stylelint-config-prettier": "^3.3.0",
  17. "stylelint-config-standard": "^18.2.0"
  18. },
  19. "scripts": { 可以添加更多命令
  20. "precommit": "npm run lint-staged",
  21. "prettier": "prettier --write "./**/*.{js,jsx,css,less,sass,scss,md,json}"",
  22. "eslint": "eslint .",
  23. "eslint:fix": "eslint . --fix",
  24. "stylelint": "stylelint "./**/*.{css,less,sass,scss}"",
  25. "stylelint:fix": "stylelint "./**/*.{css,less,sass,scss}" --fix",
  26. "lint-staged": "lint-staged"
  27. },
  28. "lint-staged": { 对提交的代码进行检查与矫正
  29. "**/*.{js,jsx}": [
  30. "eslint --fix",
  31. "prettier --write",
  32. "git add"
  33. ],
  34. "**/*.{css,less,sass,scss}": [
  35. "stylelint --fix",
  36. "prettier --write",
  37. "git add"
  38. ],
  39. "**/*.{md,json}": [
  40. "prettier --write",
  41. "git add"
  42. ]
  43. }
  44. }
  • 如果你想禁用这个功能,可以把 scripts 中 “precommit” 改成 “//precommit”
  • 如果你想自定 eslint 检查代码的规范,可以修改 .eslintrc, .eslintrc.js 等配置文件
  • 如果你想自定 stylelint 检查代码的规范,可以修改 .stylelintrc, .stylelintrc.js 等配置文件
  • 如果你想忽略某些文件不进行代码检查,可以修改 .eslintignore, .stylelintignore 配置文件

    组件化

    当项目拥有了一定量的代码之后,就会发现,有些代码是很多页面共用的,于是把这些代码提取出来,封装成一个组件,供各个地方使用。
    当拥有多个项目的时候,有些组件需要跨项目使用,一种方式是复制代码到其他项目中,但这种方式会导致组件代码很难维护,所以,一般是用另一种方式:组件化。
    组件化就是将组件独立成一个项目,然后在其他项目中安装这个组件,才能使用。
    一般组件化会配合私有 npm 仓库一起用 ``` |— project1/ 项目1 |— package.json

|— project2/ 项目2 |— package.json

|— component1/ 组件1 |— package.json

|— component2/ 组件2 |— package.json

  1. project1 中安装 component1 component2 组件:

package.json

{ “dependencies”: { “component1”: “^0.0.1”, “component2”: “^0.0.1” } }

  1. ```
  2. import compoennt1 from 'compoennt1';
  3. import compoennt2 from 'compoennt2';

测试

测试的目的在于能以最少的人力和时间发现潜在的各种错误和缺陷,这在项目更新、重构等的过程中尤其重要,因为每当更改一些代码后,你并不知道这些代码有没有问题、会不会影响其他的模块。如果有了测试,运行一遍测试用例,就知道更改的代码有没有问题、会不会产生影响。
一般前端测试分以下几种:

  1. 单元测试:模块单元、函数单元、组件单元等的单元块的测试
  2. 集成测试:接口依赖(ajax)、I/O 依赖、环境依赖(localStorage、IndexedDB)等的上下文的集成测试
  3. 样式测试:对样式的测试
  4. E2E 测试:端到端测试,也就是在实际生产环境测试整个应用

一般会用到下面的一些工具:

另外,可以参考 聊聊前端开发的测试

构建

一般单页面应用的构建会有 npm run build 的命令来构建项目,然后会输出一个 html 文件,一些 js/css/images … 文件,然后把这些文件部署到服务器就可以了。
多页面应用的构建要复杂一些,因为是多入口的,所以一般会封装构建工具,然后通过参数传入多个入口:

  1. npm run build -- page1 page2 dir1/* dir2/all --env test/prod
  • page1, page2 确定构建哪些页面;dir1/, dir2/all 某个目录下所有的页面;all, 整个项目所有的页面
  • 有时候可能还会针对不同的服务器环境(比如测试机、正式机)做出不同的构建,可以在后面加参数
  • — 用来分割 npm 本身的参数与脚本参数,参考 npm – run-script 了解详情

多页面应用会导出多个 html 文件,需要注意这些导出的 html 不要相冲突了。
当然,也可以用一些已经封装好的工具,如 lila

部署

在构建好项目之后,就可以部署到服务器了。
传统的方式,可以用 ftp, sftp 等工具,手动传到服务器,但这种方式比较笨拙,不够自动化。
自动化的,可以用一些工具部署到服务器,如 gulpgulp-ssh,当然也可以用一些封装的工具,如 md-synclila
以 md-sync 为例:

  1. npm install md-sync --save-dev

md-sync.config.js 配置文件:

  1. module.exports = [
  2. {
  3. src: './build/**/*',
  4. remotePath: 'remotePath',
  5. server: {
  6. ignoreErrors: true,
  7. sshConfig: {
  8. host: 'host',
  9. username: 'username',
  10. password: 'password'
  11. }
  12. },
  13. },
  14. {
  15. src: './build/**/*.html',
  16. remotePath: 'remotePath2',
  17. server: {
  18. ignoreErrors: true,
  19. sshConfig: {
  20. host: 'host',
  21. username: 'username',
  22. password: 'password'
  23. }
  24. },
  25. },
  26. ];

在 package.json 的 scripts 配置好命令:

  1. "scripts": {
  2. "deploy": "md-sync"
  3. }
  1. npm run deploy

另外,一般大型项目会使用持续集成 + shell 命令(如 rsync)部署。

持续集成测试、构建、部署

一般大型工程的的构建与测试都会花很长的时间,在本地做这些事情的话就不太实际,这就需要做持续集成测试、构建、部署了。
持续集成工具用的比较多的:

jenkins 是通用型的工具,可以与 githubbitbucketgitlab 等代码托管服务配合使用,优点是功能强大、插件多、社区活跃,但缺点是配置复杂、使用难度较高。
gitlab ci 是 gitlab 内部自带的持续集成功能,优点是使用简单、配置简单,但缺点是不及 jenkins 功能强大、绑定 gitlab 才能使用。
以 gitlab 为例(任务定义在 .gitlab-ci.yml 中):

  1. stages:
  2. - install
  3. - test
  4. - build
  5. - deploy
  6. # 安装依赖
  7. install:
  8. stage: install
  9. only:
  10. - dev
  11. - master
  12. script:
  13. - npm install
  14. # 运行测试用例
  15. test:
  16. stage: test
  17. only:
  18. - dev
  19. - master
  20. script:
  21. - npm run test
  22. # 编译
  23. build:
  24. stage: build
  25. only:
  26. - dev
  27. - master
  28. script:
  29. - npm run clean
  30. - npm run build
  31. # 部署服务器
  32. deploy:
  33. stage: deploy
  34. only:
  35. - dev
  36. - master
  37. script:
  38. - npm run deploy

以上配置表示只要在 dev 或 master 分支有代码推送,就会进行持续集成,依次运行:

  • npm install
  • npm run test
  • npm run clean
  • npm run build
  • npm run deploy

最终完成部署。如果中间某个命令失败了,将停止接下的命令的运行,并将错误报告给你。
这些操作都在远程机器上完成。
到这里为止,基本上完成了一个项目的搭建、编写、构建。

清理服务器上过期文件

现在前端的项目基本上都会用 webpack 打包代码,并且文件名(html 文件除外)都是 hash化的,如果需要清除过期的文件而又不想把服务器上文件全部删掉然后重新构建、部署,可以使用 sclean 来清除过期文件。

收集前端错误反馈

当用户在用线上的程序时,怎么知道有没有出 bug;如果出 bug 了,报的是什么错;如果是 js 报错,怎么知道是那一行运行出了错?
所以,在程序运行时捕捉 js 脚本错误,并上报到服务器,是非常有必要的。
这里就要用到 window.onerror 了:

  1. window.onerror = (errorMessage, scriptURI, lineNumber, columnNumber, errorObj) => {
  2. const data = {
  3. title: document.getElementsByTagName('title')[0].innerText,
  4. errorMessage,
  5. scriptURI,
  6. lineNumber,
  7. columnNumber,
  8. detailMessage: (errorObj && errorObj.message) || '',
  9. stack: (errorObj && errorObj.stack) || '',
  10. userAgent: window.navigator.userAgent,
  11. locationHref: window.location.href,
  12. cookie: window.document.cookie,
  13. };
  14. post('url', data); // 上报到服务器
  15. };

线上的 js 脚本都是压缩过的,需要用 sourcemap 文件与 source-map 查看原始的报错堆栈信息,可以参考 细说 js 压缩、sourcemap、通过 sourcemap 查找原始报错信息 了解详细信息。

转载于:https://blog.csdn.net/weixin_34146986/article/details/91516493