Eisen's Blog

© 2024. All rights reserved.

Webpack Setup

2016 May-05

虽然用 webpack 有一阵子了,但是上次构建整个体系的时候手忙脚乱的,仅仅是找了乱七八糟的东西堆叠起来,中间的过程忘的一干二净今天去 review 自己以前写的代码完全不知道自己是怎么搞定的。这次写一个小系列把如何构建 webpack + redux + react 的体系记下来,今天是第一部分,webpack 的准备工作。

webpack 可以认为就是一个 node 版本的 make 吧,不过自然是有 js 特色的 make 了,类似的东西有很多,比如 browserify 以及 gulp 等。webpack 最终的目的就是将我们一个有众多文件的 js 的 project 变成只有一个或者多个文件的 bundles,我在后面会结合例子做展示。并且webpack 可以支持 loader 将各种诡异的 js 方言转换成 js 比如当下比较流行的额 babel jsx 等,所以 webpack 配合 es2015 以及 react 一起使用非常的方便。不过要说明的是对这些方言的支持是 loader 的事情,webpack 本身是只能处理原生态的 js 的。

basic

首先自然是安装 webpack

npm install -g webpack
npm install -S webpack

然后我展示一个 webpack 的基本用法。首先看一下我们的目录结构:

├── index.html
├── index.js
├── module1.js
├── module2.js
└── package.json

其中 index.html 基本就是一个空文件

<html>
  <head>
    <meta charset="utf-8">
    <title>index</title>
  </head>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>

module1.js module2.js 展示如下

console.log('module 1');
console.log("module 2");

index.js 通过 require 的方式引用两个模块

require("./module1");
require("./module2");

然后通过命令 webpack ./index.js bundle.js 可以将 index.js 以及其所依赖的模块打包生成一个文件 bundle.js 这样在浏览器打开 index.html 就可以看到 console 中的命令了。

use webpack.config.js

在上述这么简单的情况下我们就仅仅用 webpack 的命令就可以了。不过在处理更复杂的事情的时候需要 webpack.config.js 来帮忙。这里我给出一个最小化的 webpack.config.js 的实例来替代刚才的命令。

var path = require("path");

module.exports = {
  entry: [
    './index'
  ],
  output: {
    path: path.join(__dirname, "dist"),
    filename: "bundle.js"
  }
};

其中,entry 就是我们整个 projectmain。就如在前文中 webpack ./index.js bundle.js./index.js 的角色。output 则表示我们要将生成的 js 放在哪里。这里我提供了一个不同的 path: dist,然后依然采用 bundle.js 的名字。这样我们执行 webpack 就可以看到 dist 下出现了 bundle.js 这个文件。

use webpack dev server

那么每次改了文件之后都 webpack 是不是很麻烦,应该是有 watch 的办法吧。对的,这就是 webpack-dev-server 了。首先安装它。

npm install -g webpack-dev-server
npm install -S webpack-dev-server
执行 `webpack-dev-server --inline --hot --content-base dist/`,每次修改代码就可以自动 build 了。

既然这里我们把 content-base 设定为了 dist 那么需要把 index.html 放进去啦。最后的目录结构是这样子的:

├── dist
│   ├── bundle.js
│   └── index.html
├── index.js
├── module1.js
├── module2.js
├── package.json
└── webpack.config.js

值得一提是在 package.json 里有一个专门放置这种启动 server 的地方,就是在 scripts 下:

{
  "name": "webpack-setup",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "webpack": "^1.13.0"
  }
}

然后下次执行 npm start 就可以启动这个 dev server 啦。

一些参考

  1. webpack.config.js https:://webpack.github.io/docs/configuration.html
  2. webpack dev server https:://webpack.github.io/docs/webpack-dev-server.html

Some tips about DDD

2016 April-20

DDD 即 Domain Driven Design,领域驱动设计,似乎是一个比较老的东西了,2003 年这本书就出版了。不过这么多年来我是从来都没有知晓过,直到参加了小巨人的培训。在培训的过程中,我自己尝试自己对某个领域进行建模并且以 REST API 的形式实现自己的设计,而整个过程中都要尽量的遵循 DDD 的一些设计原则,可惜培训时间太短了,我需要更多的时间去消化。半年多来我一直都在琢磨这个主题,即使工作任务很重的时候我依然在尝试把以前自己认为不遵循 DDD 设计的一些项目按照我理解的 DDD(对,我理解的,不代表是对的)进行了重写,这虽然花了不少的时间但我认为这是值得的。其中经常出现的几个名词 aggregate value object entity bounded context domain model repository factory 一直以来我总觉得自己没有把它们彻底的搞明白。整个体系对我来说依然没有在我的脑海中建立起来。直到最近,在认认真真的看完了几本 DDD 主题的书籍以及众多有关这个主题的文章和演讲之后,我才觉得我对这方面的理解有了起色,我逐渐的弄明白了 DDD 的真正意图,清楚了 REST 和 DDD 的关系,我才敢写下这篇文章。

培训中 REST 和 DDD 的主题是被放在一起讲解的,REST 按照 DDD 中 aggregate 的形式被组织在一起。看下面这样一组 REST API:

/users
/users/:user-id
/users/:user-id/orders
/users/:user-id/orders/:order-id

user 作为一个 aggregateroot,它包含了其下所有的 order。这样最初看起来没什么不妥,order 是随着 user 出现的,order 的生命周期是受 user 控制的。这就像是 Evans 在第六章节举的那个例子,line itemorder 的一部分。但是在实现这部分 api 的时候我发现我有一点是难以做到的:order 是不能够随着 user 一起载入到内存的,它不像是 orderorder line item 那样的关系。user's orders 这个集合是可以不断的扩张的,我甚至不能把一个用户所有的 order 一次性的载入到内存中,我需要分页,我需要根据默写规则对用户的订单进行筛选。此时再仔细想想 DDD 的那个例子,里面涉及了很多的并发冲突,然而当我需要拿到用户以及查询订单的时候会有什么呢?没有,什么冲突都不会发生。逐渐的我才明白其实我一开始就理解错了。事实上,DDD 关注的是一个写模型,并发的冲突都是在有写操作的时候才会出现。例子中的创建和修改订单都是写,而我所要考虑的仅仅是读而已,读事实上什么麻烦都不会产生,怎么读都不会产生问题。

再去看看 Implementing DDD 这本书的例子,application 这个 package 被分成了两部分,一部分是 Query 一部分是 Command,没错就是 CQRS 的思路。一个个 Command 调用了 domain 中的对象和方法,实现了关键的业务。而 Query 的 Data Model 和 Domain Model 有质的区别,Query Service 甚至是直接拼装了 HQL (Hibernate SQL)。它更多的是面向 UI 的:需要展示什么就提供什么。那么这样来看,很多事情就迎刃而解了。

简单的来讲,aggregate 就是为了解决一个并发的问题。aggregate 就是定义了一个业务场景中最小的锁单元:任何人对一个 aggregate 操作时其他人都不能再对这个单元进行操作了。而整个业务中数据的一致性也是由这样的方式得到了保证。那么回到上面的例子,user 下的 order 是没有道理和 user 建立为一个 aggregate 的。userorder 分别是一个单 entityaggregte

DDD 仅仅是一个写模型。在通过 REST API 暴露一个 Domain 的接口的时候要明确每一个方法分别对应了相应资源下的什么操作。虽然很多的数据和演讲中强调 REST 和 DDD 没关系,并且 Rest 的 Resource 也和 DDD 中的 Entity 没有映射关系,但是我个人觉得从 UL 的角度来说,外部所看到的东西和 Domain 所提及的东西应当一致,只是 REST 会隐藏很多细节罢了。当然,这里所谓的隐藏细节也可能隐藏的多到内外的概念是不一致的。其中 GET 和其他操作相比有着质的区别,它可能采用了纯粹的 DTO 而不涉及任何的 Domain,这样在实现模型的时候我们就不必小心翼翼的去让 Domain Model 尽量的和 Rest 所需要获取的数据保持一致了。这也是我自己在整个过程中最困惑的地方了。

到这里,按照 DDD 设计的思路就清楚多了,我不再担心如何让 GET 方法从 Domain 中拿到它想要的东西了。我可以在设计的时候首先关注更重要的业务流程,然后在需要的时候用最简单的方式提供相应的 Query Service 即可。


新的博客

2016 March-26

之前的 blog 是搭在 SAE 的 wordpress,但是由于渣浪没有回复我的账号,我默默的看着我的 SAE 云豆消耗殆尽连个充值的机会都没有,真是不知道新浪这样的状态还能撑多久。不过不管怎么样我应该还是有机会可以把我的博客拿到的,然后赶紧的把乱七八糟的博客都导过来,毕竟那个博客也用了有 5 年了吧。

之前有尝试用 jekyll 在 github 上部署 blog,那个时候 github 对 jekyll 的支持还没有那么好,我记得是不能够自己主动的部署到 xx.github.io 上的,需要自己拉一个 branch 但是现在似乎不需要了,默认部署,方便多了。而且之前的那个默认的 template 也是太丑了,自己也没有当初调整 wordpress template 的心情了哎(所以我自己对我以前 wordpress 的 template 还是挺满意的,毕竟人家默认的 template 就不错呀)。幸好找到了现在 hux 这套给力的模板,我又有动力用 jekyll 了。好多地方还是人家 hux 的名字,我也在慢慢修改了。

github 首先应该不会在短期内挂掉吧,然后人家也是给了我一个域名,唯一一点不好就是有些 2b 的学校教育网默认不能访问国外的服务器,这我就没有办法了。