luqin / blog

My blog
https://github.com/luqin/blog/issues
64 stars 11 forks source link

基于 NPM 的大型 React 单页应用探索(多场景多方案) #10

Open luqin opened 8 years ago

luqin commented 8 years ago

基于 NPM 的大型 React 单页应用探索(多场景多方案)

未完待续……

本文目标构建基于 NPM 的大型 React 单页应用(以及多页面),支持多模块协同开发、分布式构建与发布。

首先初始化顶层目录结构:

app/
config/
package.json
README.md
... and tons of project .dotfiles and tool files ...

按文件类型组织 File-Type First (FTF)

app/
  reducers/
    root.js
    memberships.js
  components/
    home.jsx
    memberships.jsx
  ... of course more type folders/ ...

按功能组织 Feature First (Pods)

app/
  authentication/
    api/
    components/
    helpers/
    ...
  comments/
    actions/
    api/
    components/
    reducers/
    stores/
    ...
  ...

可以像这样按功能分组:

app/
  settings/
    profile/
    notifications/
  ...

那么通用文件如何放置呢?一个方案是将他们放入框架文件夹:

app/
  flux/
    apiUtils.js
    baseActions.js
    baseStore.js
    connectToStores.js

多 App 模式 Multiple Apps

app/
  kapost.jsx
  studio/
    studioEntry.jsx
    content/
    ...
  gallery/
    galleryEntry.jsx
    collections/
    ...
  insights/
    insightsEntry.jsx
    content-scoring/
    ...
  members/
    membersEntry.jsx
    profile/
    ...

依然有很多通用代码,可以放入通用文件夹:

app/
  ...
  shared/
    users/
    ui/
      dropdowns/
      ...
    ...

到目前为止,按功能组织模式仍然可以 hold 住,我们可以在每个 App 使用按文件类型组织模式,但是依然有缺点,仅仅适合单 App 模式。

面对疯狂增长的 routes 或者 reducers,还有一种优雅的方式是使用代码分包(code-splitting),例如动态加载 React Router动态增加 Redux reducers,那么我们如何组织这些文件呢?我们可以定义一个顶级文件夹 boot/,一个项目文件夹例如 kapost/

app/
  kapost/
    routes.jsx (holds and rolls up all other app routes dynamically)
    reducer.js (holds all reducers dynamically)
  studio/
    studioEntry.jsx
    app/
      routes.jsx (rolls up all application routes)
      reducers.jsx (rolls up all studio reducers across all the feature folders)
    ...
  ...

……

Application Organization

API

同构 Universal Rendering

CSS 方案:

构建工具:

本文基于 SASS 实现模块化方案。

Without webpack and inlining

每个项目的样式文件目录:

studio/
  app/
  config/
  stylesheets/
  spec/
  package.json
  ...

每个样式文件通过命名空间来实现模块化,根据组件确定前缀:

studio/
  app/
    comments/
      commentEntry.jsx
  stylesheets/
    comments/
      _commentEntry.scss
// _commentEntry.scss
.studio-comment-entry-component {
  // my name-spaced styles
}

// commentEntry.jsx#render
render() {
  <div className="studio-comment-entry-component">...</div>
}

共享的样式可以放入 shared/ 目录,全局样式可以放入类似 stylesheets/app/ 的目录(使用命名空间)。

每个 app 都负责引入所有功能模块的样式文件,顶层 app 负责引入所有子 app 的样式文件。如果分离一些 apps 到分离的代码仓库,可以共享相同的构建流程,只需要维护相同的构建配置。

With webpack and inlining

studio/
  app/
    comments/
      styles/
        individualComponentStylesheet.scss
      ...

Why You Shouldn’t Style React Components With JavaScript

Testing

studio/
  app/
    comments/
      components/
      commentsContainer.jsx
      specs/
        components/ (unit tests of sorts)
        integration/ (testing entire comment feature)
        commentsContainerSpec.jsx (container could even be the main integration test)
        ...
      ...

基于 NPM 的协同开发方案

私有 NPM 方案:

  1. 官方私有 NPM
  2. 搭建私有 NPM 仓库

NPM 分包:

@kapost/app
@kapost/studio
@kapost/gallery
@kapost/insights
...
module/
  ...
  assets
  dist
  js
  scss
  test
  tools
  routes.jsx
  package.json

……

分布式编译

AllenFang commented 8 years ago

Nice sharing

luqin commented 8 years ago

@AllenFang Thank you。先整理下资料,后续会整理出基于 npm 的多模块多项目开发协作流程及工具。

AllenFang commented 8 years ago

:+1:

luqin commented 8 years ago

@AllenFang 推荐你看看上面的两篇参考文章

AllenFang commented 8 years ago

Readed, Good articles :)