webpack工程化集成React技术栈一

项目开始前,我们先聊一聊关于项目的一些说明。该项目起始于2017年初,当时公司主要技术栈为gulp+angular,鉴于react的火热的生态,在公司决定研发bss管理系统时选用react开发,目的也是为react native打下基础,以解决后期公司大前端技术栈的逐步成熟。(当时没有选择vue开发的主要原因是weex生态还不够特别成熟),既然决定换新,项目的构建也跟着一起换,从gulp转向火热的webpack,持续大半年的更新迭代,我们将构建模块逐步从项目中抽离出来,把构建模块作为npm包单独管理,完成和项目代码解耦,于是就有了后面我们要说的wci-build构建模块包和wci-cli项目脚手架。

我们要做什么

技术栈

项目采用前后端分离的形式,后端选用Maven+SpringClould全家桶开发,前端选用webpack+react全家桶开发,前后端全部采用包管理工具完全解决项目依赖管理的难题,版本管理采用git,前后端通过json交互,swgger管理接口文档,接口全部遵循restful规范。由于本文面向社区开放,故本文中不涉及公司业务层的代码,本文全部代码均为最新编写,我们以一个旅游管理系统的三个模块为大家演示项目(登陆登出、用户模块、景点模块)。为了快速开展,本文涉及的后端代码直接采用Java的SSM框架搭建,源码也将为大家奉上。朋友们也可以使用mock模拟接口数据。后期我们在演示nodejs+espress时将接口代码全部转为node形式。

准备

因本文不是讲解基础,故大家在敲代码前,还需要具备一定的前端基础,部分如下

  1. html、css、javascript基础知识
  2. es6基础知识
  3. react基础知识
  4. 了解什么是webpack、babel、redux、react-router、nodejs、npm
  5. 熟悉蚂蚁金服ant design
  6. 熟悉less基本使用

解决什么问题

本项目集成了最新的react16、react-router4、redux,同时可以选择性集成antd|antd mobile,在解决繁琐的架构配置工作外,还解决了以下问题

通用问题
  1. 支持开发效率更高的ES6编写代码。
  2. 拆分开发、测试、生产环境,完成从开发到上线的所有工作。
  3. 开发环境包含热替换,本地IP、端口可配置,接口可配置,微服务模块可配置
  4. 测试环境包含代码压缩、合并、css抽离、公共组件抽离、代码添加hash、测试版本后缀
  5. 生产环境包含代码压缩、合并、css抽离、公共组件抽离、代码添加hash、生产版本后缀(和测试代码完全一样,只缺少测试版本号)
  6. 支持自定义添加webpack loader
其他问题
  1. 目前大型项目后端多采用微服务架构,API接口在开发、测试、生产环境下来回切换,需要频繁修改代码。解决方案:通过配置文件的方式统一配置项目模块接口
  2. 项目模块在分拆开发的过程中css命名冲突,导致代码维护性较差。解决方案:构建工具预加载css时自动化添加hash,使css代码模块化
  3. 不同开发人员,不同的代码习惯造成项目代码难以维护。解决方案:在代码编写、构建、版本管理三个方向加入代码规范校验(airbnb规范)
  4. 在同时开发多个系统的时候,构建业务模块在不同的项目都存在,当需要修改配置或者优化构建方案的时候,需要修改多个项目的配置。解决方案:抽离构建模块,采用npm形式依赖。

还有什么问题要解决

虽然经过大半年迭代,但我们还需要在实际项目开发中支持更多的个性化需求

  1. cdn自动化
  2. 更加完善的持续集成
  3. 单元测试,包括代码,交互测试
  4. mock数据,实现前后端真正0接触
  5. ...

希望

大家在开发过程中遇到任何问题,希望可以给我们留言,我们会不断优化项目。未来,我们还会加入mobx、rxjs、immutablejs、GraphQL等,也希望在和大家的探讨中,持续进步。

项目准备

本项目基础环境必须依赖nodejsnpm,未安装的朋友可以去官网自行安装,安装教程这里不详细说明,安装完成后使用如下命令,查看是否安装成功。

node -v
npm -v

初始化项目

本项目我们使用wci-cli脚手架初始化项目

  • 全局安装wci-cli
npm install -g wci-cli
  • 创建项目

wci-cli 脚手架可以创建三种项目,分别是1.纯净的react项目 2.包含antd的react项目 3.包含antd-mobile的react项目,命令如下

wci new myapp

执行命令后,命令行会提示是否需要安装antd以及选择antd类型,即可完成项目初始化,如下

项目目录

myapp
├── app // 项目业务代码
│   ├── assets // 静态文件目录(图片、字体等)
│   ├── script // js代码目录
│   │   ├── actions // redux action目录
│   │   ├── componets // react 无状态组件目录
│   │   ├── containers // react 业务代码
│   │   ├── reducers // redux reducer目录
│   │   ├── util // 工具包目录
│   │   │   ├── theme.js // antd自定义样式文件
│   │   ├── Home.js // 首页
│   │   ├── home.less // 首页样式
│   ├── styles // 全局样式目录
│   ├── index.js // 项目入口文件
│   ├── index.tpl.html // 项目html模版
├── node_modules // 依赖包目录
├── .babelrc // babel配置文件
├── .eslintrc // eslint代码校验配置文件
├── .gitignore
├── package.json
├── README.md
├── wci.json // wci项目配置文件(主要配置一些开发、测试、生产环境的信息)
└── webpack.js // webpack自定义配置文件

执行如下命令,运行开发环境

cd myapp
npm run start

如上图,我们的项目已经跑起来了...

  • 测试、发布

因我们需要保证测试代码和生产代码必须保持一致,所有在实际项目中,我们可以运行如下命令构建代码

npm run test // 测试环境打包
npm run dist // 生产环境打包

测试代码

生产代码

到这里,我们已经完成项目前期开发的所有准备工作,接下来,我们一起开始撸代码吧

项目结束后,我会为大家奉上两篇彩蛋,分别是 1. 一步步搭建webpack前端构建工具并抽成npm单独模块 2. 一步步构建自己的npm开发包并且以一个真实例子演示(开发一个命令行生成文件夹结构的小工具)

还要说一点

正式开始撸代码前,还要针对项目具体说明,包括项目代码目录介绍,前后端分离项目需要注意哪些问题,前后端如何鉴权等...

都是干什么的

myapp
├── app // 项目业务代码
│   ├── assets // 静态文件目录(图片、字体等)
│   ├── script // js代码目录
│   │   ├── actions // redux action目录
│   │   ├── componets // react 无状态组件目录
│   │   ├── containers // react 业务代码
│   │   ├── reducers // redux reducer目录
│   │   ├── util // 工具包目录
│   │   │   ├── theme.js // antd自定义样式文件
│   │   ├── Home.js // 首页
│   │   ├── home.less // 首页样式
│   ├── styles // 全局样式目录
│   ├── index.js // 项目入口文件
│   ├── index.tpl.html // 项目html模版
├── node_modules // 依赖包目录
├── .babelrc // babel配置文件
├── .eslintrc // eslint代码校验配置文件
├── .gitignore
├── package.json
├── README.md
├── wci.json // wci项目配置文件(主要配置一些开发、测试、生产环境的信息)
└── webpack.js // webpack自定义配置文件

以上是代码的全部目录,下面我们根据功能依次介绍:

  • node_modules、.gitignore、package.json、README.md
node_modules: npm依赖包目录,开发者可以不用管,只要知道我们项目里所有的依赖都下载在这个文件夹下
.gitignore:git需要忽略的文件
package.json:npm最主要的文件,里面写满了我们依赖包的结构和一些项目信息
README.md:github的说明文件
  • .babelrc、.eslintrc
.babelrc:babel配置文件,可以配置部分自定义babel插件(例如本项目里antd自定义主题和javascript@语法糖就在这里配置)
.eslintrc:eslint配置文件,可以自定义配置eslint规则,详细规则可以去官网 eslint查看

说明:这两个模块本该配置在wci-build构建工具里,但考虑到项目的灵活性,所有抽离出来放在项目根目录

  • webpack.js
webpack.js:webpack loader个性化的配置文件,可以自定义添加webpack loader
  • wci.json
wci.json:项目的配置文件,可以自定义配置项目
{
  "index": "app/index.js",// 项目入口文件
  "hostname": "127.0.0.1",// 开发环境IP地址(可以配置域名通过本地host转发)
  "name": "wci-antd-app",// 项目名称(显示在浏览器title里的名字)
  "libs": [ // 项目的公共包,后续可以自行添加
    "react","react-dom","axios","classnames","prop-types","react-redux","react-router-dom","redux","redux-thunk"
  ],"dev": { // 开发环境配置
    "port": 8031,// 开发环境端口
    "src": "app",// 开发环境监听目录
    "api": "",// 开发环境后端接口地址
    "module": {},// 开发环境的模块包
    "is_eslint": false // 开发环境是否开启eslint校验
  },"test": { // 测试环境配置
    "module": {},// 测试环境的模块包
    "api": "" // 测试环境后端接口地址
  },"prod": { // 生产环境配置
    "module": {},// 生产环境的模块包
    "api": "" // 生产环境后端接口地址
  }
}
  • app
项目目录
├── app // 项目业务代码
│   ├── assets // 静态文件目录(图片、字体等)
│   ├── script // js代码目录
│   │   ├── actions // redux action目录
│   │   ├── componets // react 无状态组件目录
│   │   ├── containers // react 业务代码
│   │   ├── reducers // redux reducer目录
│   │   ├── util // 工具包目录
│   │   │   ├── theme.js // antd自定义样式文件
│   │   ├── Home.js // 首页
│   │   ├── home.less // 首页样式
│   ├── styles // 全局样式目录
│   ├── index.js // 项目入口文件
│   ├── index.tpl.html // 项目html模版

如上,因为react遵循组件化开发,故我们的业务代码全部写在containers目录下,并且模块的样式文件、高阶组件写在相对的模块下,如图

styles目录用于存放项目全局的样式文件,例如全局样式的变量文件等...

其他

版本管理:

推荐使用gitflow来进行版本的管理,这里不做详细描述

前后端分离跨域:

一旦项目采用前后端分离,跨域是所有项目里不可避免的问题,目前跨域的解决方案主要有三种

  1. 采用jsonp方式(只支持GET请求)
  2. 采用cors方式
  3. 采用node中间件方式(需要单独部署nodejs服务)

我们这里采用方式2

java代码
response.addHeader("Access-Control-Allow-Origin","*");
response.addHeader("Access-Control-Allow-Credentials","true");
response.addHeader("Access-Control-Allow-Headers","Content-Type,Content-Token,Content-User,X-Requested-With");
nodejs 代码
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Headers",X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1')
res.header("Content-Type","application/json;charset=utf-8");

这种方式还可以自定义请求头的认证信息

不明白的朋友可以去看阮一峰大神的这篇文章

未完待续 更新于2018-02-26

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom