haizlin / fe-interview

前端面试每日 3+1,以面试题来驱动学习,提倡每日学习与思考,每天进步一点!每天早上5点纯手工发布面试题(死磕自己,愉悦大家),6000+道前端面试题全面覆盖,HTML/CSS/JavaScript/Vue/React/Nodejs/TypeScript/ECMAScritpt/Webpack/Jquery/小程序/软技能……
http://www.h-camel.com
MIT License
25.32k stars 3.25k forks source link

[vue] 从0到1自己构架一个vue项目,说说有哪些步骤、哪些重要插件、目录结构你会怎么组织 #983

Open Brass-neck opened 5 years ago

Brass-neck commented 5 years ago

从0到1自己构架一个vue项目,说说有哪些步骤、哪些重要插件、目录结构你会怎么组织

josh-axy commented 5 years ago

要看是vue.js还是vue cli项目,如果是vue.js可以按照普通web项目流程开发,只在代码架构上变为数据和模型分离的模式即可。 如果是vue cli项目,不仅要分离数据和模型,还要理解vue router, vuex等组件,并且对于组件化的概念要更加透彻,由其是单页面应用,每个子页面如何组件化是必须在项目伊始就想清楚的。

tiandashu commented 5 years ago

vue cli项目目录:pages、servers、config(项目的配置非cli的)、utils、doc(必要的文档记录)

brady0316 commented 5 years ago

vue-cli实际上已经很成熟了,目录除了脚手架默认的, 1、一般会额外创建views,components,api,utils,stores等; 2、下载重要插件,比如axios,dayjs(moment太大),其他的会根据项目需求补充; 3、封装axios,统一api调用风格和基本配置; 4、如果有国际化需求,配置国际化; 5、开发,测试和正式环境配置,一般不同环境API接口基础路径会不一样;

censek commented 5 years ago
  1. 安装node.js
  2. 安装vue:npm install vue -g
  3. 安装webpack:npm install webpack -g
  4. 安装vue-cli:npm install vue-cli -g

构建项目: vue init webpack 文件名

xiuxiuyifan commented 5 years ago

我以为有答案的

wujie520303 commented 4 years ago

我来简单说一下我的见解吧,有些简单浅显(小学语文真的没学好),目的在于提供一个思路供大家参考。

项目类型

前端的项目目前来看主要分为小程序开发,H5页面开发、PC官网后台管理系统开发、Native开发。不同的项目所涉及的知识点和环境不太一样,但是很多方面是相通的。

由于框架限定在Vue,所以这里指的是使用mpvueWePY来开发小程序项目。

这里主要是指微信页面、Webview中的H5页面开发

为什么单独划出来是因为官方的开发主要是用来展示企业信息、产品,对交互、体验有一定的要求,会有一些炫酷的动画效果。还有就是官网有可能需要采用SSR(比如Vue的Nuxt.js)来做,来确定良好的SEO。

后台管理系统主要功能在于数据的配置、权限的控制、数据报表的展示、日志功能等。通常又叫CMSOA

这个通常就是指用前端技术去开PC应用、APP应用,比如Weex, Electron

比如uni-app, 可以一套代码编译成不同的平台源码。

不同的项目类型决定了其能够使用的生态、目录结构、特定的上下文。这里就以后台管理系统为例来说一下如何基于Vue来搭建一个项目。

注: 我只会玩这个,凑合阅读吧

基于@vue/cli的选型

后台管理系统中vue-routervuex都是必选的,其它可以自行考虑。

通过 @vue/cli 生成项目后,接下来就是添加一些配置文件

通用配置

一个前端项目在开发过程中少不了各种框架、IDE的配置文件。前端项目的配置文件通常格式有xx.json.xxrcxx.config.jsxxconfig等方式。

这里最重要的是缩进方式,及Tab大小,建议2个空格作用缩进。

# https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

这里的配置决定了哪些文件会被版本控制所忽略

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

# editor
/.idea

说实话eslint要是配置不好,代码在IDE中提示真的很恶心,但是配置项又太多,还有很多专有的扩展,这里给出我的一个配置(也是到处copy过来的)

module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: ["plugin:vue/strongly-recommended"],
  rules: {
    "no-console": process.env.NODE_ENV === "production" ? "error" : "off",
    "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
    // 不加分号
    "semi": [0],
    // 不能有未定义的变量
    "no-undef": 1,
    // 不能有声明后未被使用的变量或参数
    "no-unused-vars":[2, {
      "vars": "local",
      "args": "none"
    }],
    // 禁止修改const声明的变量
    "no-const-assign": 2,
    // 函数参数不能重复
    "no-dupe-args": 2,
    // 如果if语句里面有return,后面不能跟else语句
    "no-else-return": 2,
    // 块语句中的内容不能为空
    "no-empty": 2,
    // 禁止对null使用==或!=运算符
    "no-eq-null": 2,
    // 禁止扩展native对象
    "no-extend-native": 2,
    // 禁止不必要的函数绑定
    "no-extra-bind": 2,
    // 禁止非必要的括号
    "no-extra-parens": 2,
    // 禁止多余的冒号
    "no-extra-semi":2,
    // 禁止省略浮点数中的0 .5 3.
    "no-floating-decimal": 2,
    // 禁止行内备注
    "no-inline-comments": 0,
    // 不能有不规则的空格
    "no-irregular-whitespace": 2,
    // 不能用多余的空格
    "no-multi-spaces": 1,
    // 禁止重复声明变量
    "no-redeclare": 2,
    // 禁止使用javascript:void(0)
    "no-script-url": 0,
    // 禁止稀疏数组, [0,,2]
    "no-sparse-arrays": 2,
    // 禁止使用三目运算符
    "no-ternary": 0,
    // 一行结束后面不要有空格
    "no-trailing-spaces": 1,
    // 标识符不能以_开头或结尾
    "no-underscore-dangle": 1,
    // 是否允许非空数组里面有多余的空格
    "array-bracket-spacing": [2, "never"],
    // 箭头函数用小括号括起来
    "arrow-parens": 0,
    // =>的前/后括号
    "arrow-spacing": 0,
    // 块语句中使用var
    "block-scoped-var": 0,
    // 逗号风格,换行时在行首还是行尾
    "comma-style": [2, "last"],
    // 避免不必要的方括号
    "dot-notation": [0, { "allowKeywords": true }],
    // 必须使用全等
    "eqeqeq": 2,
    // 对象字面量中冒号的前后空格
    "key-spacing": [0, {
      "beforeColon": false,
      "afterColon": true
    }],
    // 变量声明后是否需要空一行
    "newline-after-var": 0,
    // 引号类型 `` "" ''
    "quotes": [1, "single"],
    // 变量声明时排序
    "sort-vars": 0,
    // 禁止比较时使用NaN,只能用isNaN()
    "use-isnan": 2,
    //jsx中使用单引号
    "jsx-quotes": ["error", "prefer-single"],
    // 单个组件无内容自结尾
    "vue/html-self-closing": ["error", {
      "html": {
        "void": "always",
        "normal": "always",
        "component": "always"
      },
      "svg": "always",
      "math": "always"
    }],
    // 设置html缩进
    "vue/html-indent": ["error", 2, {
      "attribute": 2,
      "baseIndent": 1,
      "closeBracket": 0,
      "alignAttributesVertically": false,
      "ignores": []
    }],
    // 属性顺序
    "vue/attributes-order": 1,
    // 注释前面需要添加空格
    "spaced-comment": ["error", "always", { "exceptions": ["-", "+"] }],
    // html属性赋值等号左右不能有空格
    "vue/no-spaces-around-equal-signs-in-attribute": ["error"],
    // 强制prop以驼峰命名
    "vue/prop-name-casing": ["error", "camelCase"],
    // 移除多余不使用的空格
    "vue/no-multi-spaces": ["error", {
      "ignoreProperties": false
    }],
    // html结尾 >
    "vue/html-closing-bracket-newline": ["error", {
      "singleline": "never",
      "multiline": "never"
    }],
    // 属性每行数量
    "vue/max-attributes-per-line": ["error", {
      // 一行最多3个属性
     "singleline": 3,
      "multiline": {
        "max": 1,
        "allowFirstLine": true
      }
    }],
    // 单行html元素内容是否换行
    "vue/singleline-html-element-content-newline": ["error", {
      "ignoreWhenNoAttributes": true,
      "ignoreWhenEmpty": true,
      "ignores": [
        "pre",
        "textarea",
        "span",
        "i",
        "label",
        "el-button",
        "el-radio",
        "el-checkbox",
        "el-link",
        "el-tab-pane",
        "el-dropdown-item",
        "el-step",
        "el-table-column",
        "el-option"
      ]
    }]
  },
  parserOptions: {
    parser: "babel-eslint"
  }
};

这个文件自动生成,里面的内容就是指定autoprefixer兼容配置

主要是配置Babel的pluginspresetsparse

如果代码对样式有一定的规范的话,可以加一个,没有就不需要配置这个。

{
  "extends": "stylelint-config-standard",
  "plugins": ["stylelint-scss"]
}

在这个里面我们可以对@vue/cli的Webpack进行配置和覆盖。

module.exports = {
  devServer: {
    proxy: {
      '/kpi': {
        target: process.env.VUE_APP_KPI_API,
        changeOrigin: true
      }
    }
  }
}

因为在webpack中不能识别@vue/cli中的@路径,所以需要一个配置文件让webapck提示正常。具体怎么配置可以自行搜索。

'use strict'
const path = require('path')

function resolve (dir) {
  return path.join(__dirname, '.', dir)
}

module.exports = {
  context: path.resolve(__dirname, './'),
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src'),
      '_c': resolve('src/components')
    }
  }
}

这里主要是配置基于vscode的代码调试以及eslint配置。

版本控制

不管是多人协作开发还个一个人开发在使用git时都需要一套流程规范来执行。

这个每个团队的做法不太一样,有的采用多分支开发,有的采用单一master分支开发,有的还采用submodule的方式,有的在项目中使用了lerna来做多packages,甚至有的公司一个分支一个项目。

在开发环境的区分上通常分为生产(线上)环境预发布环境开发环境,有的还有什么沙盒环境,很多做得好的公司基于Docker前后端都可以根据每一个commit来发布。

有时候不想把有些代码提交上去,除了选择性提交单个文件外,还有使用git的stash功能,此外如果使用Webstorm可还可以使用其提供的Changelist来缓存修改,切换分支。

项目提交的描述如果没有一定的规范,随性而为的话,就会让其它人误解。通常提交采用英文作为描述,可以多行文字。在社区中有很多流行的方案(比如Conventional Commit),更多的是采用Angular的方式。

如果采用了社区统一的commit方式,那么我们就可以基于提交来生成变更记录,在每一次版本发布时自动关联Jira中的Issue。

这个通常是按照Semantic Versioning的规范来打tag,具休怎么做可以自行尝试

在项目中通常使用gitHookshusky这二个node包来配置上面提到的这些。在git钩子中我们在每次提交、push前跑一次单元测试、代码覆盖率。前端代码覆盖率一般来说没有必要加,不然很痛苦。

下面是package.json文件中相关的配置示例(试验性代码)

{
  "name": "your-project-name",
  "version": "0.1.0",
  "scripts": {
    "clean": "rm -rf node_modules",
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint --no-fix",
    "stylelint": "stylelint src/**/*.{scss,css,less,css,vue,jsx} --fix",
    "eslint": "eslint --ext .js,.jsx,.vue src --fix",
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
  },
  "repository": {
    "type": "git",
    "url": "http://gitlab.transsion.com/mi/mi-bigdata-admin.git"
  },
  "dependencies": {},
  "devDependencies": {
    "@commitlint/cli": "^8.1.0",
    "@commitlint/config-conventional": "^8.1.0",
    "babel-eslint": "^10.0.1",
    "conventional-changelog-cli": "^2.0.23",
    "eslint": "^6.2.1",
    "eslint-plugin-vue": "^5.2.3",
    "husky": "^3.0.4",
    "lint-staged": "^9.2.3",
    "stylelint": "^10.1.0",
    "stylelint-config-standard": "^18.3.0",
    "stylelint-scss": "^3.9.4",
  },
  "gitHooks": {
    "pre-commit": "lint-staged"
  },
  "lint-staged": {
    "*.{js,vue}": [
      "vue-cli-service lint",
      "eslint --fix --ext .js,.vue src",
      "git add"
    ],
    "*.{css,scss,less,vue}": [
      "stylelint --fix",
      "git add"
    ]
  },
  "husky": {
    "hooks": {
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  }
}

项目文档和组件测试文档

除了在项目根目录放一个README.MD文件外,通常还需要一些比如CHANGELOG.md, PLAD.md等文档,还有一些组件的使用文档,可以考虑使用styleguidestorybook

持续集成和部署

目前开源项目通常采用Travis,而一般公司内部项目通常采用Jenkins来做持续集成,在部署上通常采用Docker,集群上使用KubeOperator来管理。

 API请求方式

通常采用Restfull的方式来请求数据,也可以采用GraphQL的方式来请求。如果采用Restfull的方式通常可以使用axios, fetch api。GraphQL可以使用Apollo Client。

代理和数据Mock

SPA页面开发通常都是配置代码来调用后端的接口数据,怎么配置可以参考@vue/cli文档。数据Mock主要用到一个mockjs,至于怎么起服务自行搜索。

项目用到的库

下面这些库可以在所有项目中使用

注:UI风格目前有Bookstrap、Antd和Google Materials三种风格,在项目搭建时这也是一个很重要的技术选型。

注:这些只是我能想到的

项目目录划分

权限配置

主要分为页面权限(路由)、功能权限,采用多级角色划分方式。菜单配置数据直接通过接口返回

最后

由于回答比较仓促,项目中很多细节并没有展开说明(展开估计要长篇大论,也不一定能说清楚)。忙着下班,所有以后面就没有章法的乱写了,我平时也很少写东西,很多知识点还是多去参考一下一些不错的文章来学习吧。

最后欢迎光顾我的半年不更新的博客: jenemy

YUN-RU-TSENG commented 3 years ago

目前經驗偏向中小型專案,在架構項目前通常會花一些時間做預先的規劃。

規劃

一開始會先依照需求以及設計圖列出此次的開發項目,並在開始專案前將各個功能依據重要性分級,排定開發的順序,若是有不熟悉的功能則會規劃時間學習。

在確認需要開發的功能以及邏輯後,思考流程,以及與後端確認頁面所需求的資料,並且共同討論頁面 API 該如何規劃。預先規劃出每個頁面的 component、共用 component 名稱、切分範圍,component 負責呈現資料以及包含一些組件的邏輯功能、views 則管理該頁面的資料。


事前規劃都告一段落後,接著便可以構建架構,會透過 Vue-cli 建構(自己從頭建立太苦啦),創建時會選擇以下插件:


開發

接著建好專案後,通常會依照需求裝入以下插件:

專案目錄大致如下,將剛剛預先規劃的 component、views 先建立好,接著便可以開始切分組件 css:

src
├── App.vue
├── assets
│   ├── img
│   │   ├── access_time-24px.svg
│   │   ├── accessibility_new-24px.svg
│   │   ├── add_circle_outline-24px.svg
│   │   ├── alarm.svg
│   │   ├── apps-24px.svg
│   └── scss
│       ├── abstracts
│       ├── base
│       ├── main.scss
│       └── plugin
├── components
│   ├── Base
│   │   ├── BaseCard.vue
│   │   ├── BaseCol.vue
│   │   ├── BaseLoadCard.vue
│   │   ├── BaseRow.vue
│   │   └── FlexSystem.md
│   ├── Home
│   │   ├── HomeChart.js
│   │   ├── HomeItem.vue
│   │   ├── HomeNavbar.vue
│   │   ├── HomeSideBar.vue
│   │   └── HomeSortbar.vue
│   └── Information
│       └── InformationChart.js
├── main.js
├── router
│   └── index.js
├── service
│   ├── api.js
│   └── dayFormate.js
├── store
│   └── index.js
└── views
    ├── Home.vue
    └── Information.vue

頁面路由及組件樣式切分完成,接著便可以開始開發功能以及串接資料。

hc3001 commented 3 years ago

1、整个项目需求分析,按需求确定基本的技术栈,以及整体逻辑。 2、vue-cli 脚手架搭建,涉及到webpack,如有脚手架不满足的需求,需要做调整,如项目环境在域名的二级目录,图片、字体路径修改等。 3、开发、测试、预发布、正式环境配置,以及package.json script 脚本补充。 4、涉及到https,需要兼容http。 5、增加目录:assets、layouts 、api、component、libs、plugin、router、store。(有本地mock习惯的加上mock目录),store内部目录划分。 6、安装必须的库并引入,例如ui框架、babel、axios, 写好axios 拦截组件。 7、写好或copy常用的小插件,比如时间转换、cookie设置获取、千分位设置、邮箱校验等 8、git 工作流程梳理以及版本发布注意事项。 9、.editorconfig配置、 .gitignore 配置, readme 书写 以上基本是我工作几年的经验。

crush2020 commented 3 years ago

我一般使用vue cli创建vue项目,此时我会优先安装vue-router,vuex,axios等组件,然后根据项目,组织目录结构,创建路由,和决定封不封装axios,然后再把项目中需要用等一些组件找到并下载安装,其他的在制作项目中在一一解决。

2420687171 commented 1 year ago

https://github.com/haizlin/fe-interview/issues/983#issuecomment-546895784)https://github.com/haizlin/fe-interview/issues/983#issuecomment-546895784