-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: translate tutorials/progressive.md to English version (#966)
- Loading branch information
1 parent
35fa5a9
commit 5b959e0
Showing
1 changed file
with
219 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
title: Progressive Development | ||
--- | ||
|
||
Egg provides both [Plugin](../advanced/plugin.md) and [Framework](../advanced/framework.md), and the former has two loading modes includes `path` and `package`. Then how should we choose? | ||
|
||
Step-by-step example will be provided to demonstrate how to start coding development progressively. | ||
|
||
Find detail codes on [eggjs/examples/progressive](https://github.com/eggjs/examples/tree/master/progressive). | ||
|
||
## Getting Started | ||
|
||
Assume we are writing a code to analyze UA to implement the function below: | ||
|
||
- `ctx.isAndroid` | ||
- `ctx.isIOS` | ||
|
||
You can easily write it down after previous tutorials, let's have a quick review: | ||
|
||
Codes refer to [step1](https://github.com/eggjs/examples/tree/master/progressive/step1). | ||
|
||
Directory structure: | ||
|
||
```bash | ||
example-app | ||
├── app | ||
│ ├── extend | ||
│ │ └── context.js | ||
│ └── router.js | ||
├── test | ||
│ └── index.test.js | ||
└── package.json | ||
``` | ||
|
||
Core code: | ||
|
||
```js | ||
// app/extend/context.js | ||
module.exports = { | ||
get isIOS() { | ||
const iosReg = /iphone|ipad|ipod/i; | ||
return iosReg.test(this.get('user-agent')); | ||
}, | ||
}; | ||
``` | ||
|
||
## Prototype of Plugin | ||
|
||
Obviously, the logic is universal that can be written as a plugin. | ||
|
||
But since function might not perfect at the beginning, it might difficult to maintain if encapsulate into a plugin directly. | ||
|
||
We can put the code as the format of plugin, but not separate out. | ||
|
||
Codes refer to [step2](https://github.com/eggjs/examples/tree/master/progressive/step2). | ||
|
||
New directory structure: | ||
|
||
```bash | ||
example-app | ||
├── app | ||
│ └── router.js | ||
├── config | ||
│ └── plugin.js | ||
├── lib | ||
│ └── plugin | ||
│ └── egg-ua | ||
│ ├── app | ||
│ │ └── extend | ||
│ │ └── context.js | ||
│ └── package.json | ||
├── test | ||
│ └── index.test.js | ||
└── package.json | ||
``` | ||
|
||
Core code: | ||
|
||
- `app/extend/context.js` move to `lib/plugin/egg-ua/app/extend/context.js`. | ||
|
||
- `lib/plugin/egg-ua/package.json` to declare plugin. | ||
|
||
```json | ||
{ | ||
"eggPlugin": { | ||
"name": "ua" | ||
} | ||
} | ||
``` | ||
|
||
- `config/plugin.js` use `path` to mount the plugin. | ||
|
||
```js | ||
// config/plugin.js | ||
const path = require('path'); | ||
exports.ua = { | ||
enable: true, | ||
path: path.join(__dirname, '../lib/plugin/egg-ua'), | ||
}; | ||
``` | ||
|
||
## Extraction to Independent Plugin | ||
|
||
The module's functions become more better after a period of developing so we could extract it out as an independent plugin. | ||
|
||
We extract an egg-ua plugin and have a quick review as below. Details refer to [Plugin](../advanced/plugin.md). | ||
|
||
Directory structure: | ||
|
||
```bash | ||
egg-ua | ||
├── app | ||
│ └── extend | ||
│ └── context.js | ||
├── test | ||
│ ├── fixtures | ||
│ │ └── test-app | ||
│ │ ├── app | ||
│ │ │ └── router.js | ||
│ │ └── package.json | ||
│ └── ua.test.js | ||
└── package.json | ||
``` | ||
|
||
Codes refer to [step3/egg-ua](https://github.com/eggjs/examples/tree/master/progressive/step3/egg-ua). | ||
|
||
Then modify the application, details refer to [step3/example-app](https://github.com/eggjs/examples/tree/master/progressive/step3/example-app). | ||
|
||
- Remove directory `lib/plugin/egg-ua`. | ||
- declare dependencies `egg-ua` in `package.json`. | ||
- change type to `package` in `config/plugin.js`. | ||
|
||
```js | ||
// config/plugin.js | ||
exports.ua = { | ||
enable: true, | ||
package: 'egg-ua', | ||
}; | ||
``` | ||
|
||
**Note:We can use `npm link` for local test before releasing the plugin. Details refer to [npm-link](https://docs.npmjs.com/cli/link).** | ||
|
||
```bash | ||
$ cd example-app | ||
$ npm link ../egg-ua | ||
$ npm i | ||
$ npm test | ||
``` | ||
|
||
## Finally: A Framework | ||
|
||
After repeating the process above, we accumulate a few plugins and configurations, and might found that most of our team projects are using them. | ||
|
||
At that time, you can consider to abstract them as a framework which suitable for business scenarios. | ||
|
||
Firstly, abstract the example-framework as below. Let's have a quick review, details refer to [Framework](../advanced/framework.md). | ||
|
||
Directory structure: | ||
|
||
```bash | ||
example-framework | ||
├── config | ||
│ ├── config.default.js | ||
│ └── plugin.js | ||
├── lib | ||
│ ├── agent.js | ||
│ └── application.js | ||
├── test | ||
│ ├── fixtures | ||
│ │ └── test-app | ||
│ └── framework.test.j. | ||
├── README.md | ||
├── index.js | ||
└── package.json | ||
``` | ||
|
||
- Codes refer to [example-framework](https://github.com/eggjs/examples/tree/master/progressive/step4/example-framework). | ||
- Remove the dependencies of plugins such as `egg-ua` and remove it from example-app, then configure them into the `package.json` and `config/plugin.js` of the framework. | ||
|
||
Then modify the application, details refer to [step4/example-app](https://github.com/eggjs/examples/tree/master/progressive/step4/example-app). | ||
|
||
- Remove declaring dependencies `egg-ua` in `config/plugin.js`. | ||
- Remove dependencies `egg-ua` in `package.json`. | ||
- declare dependencies `example-framework` in `package.json` and configure the `egg.framework`. | ||
|
||
```json | ||
{ | ||
"name": "progressive", | ||
"version": "1.0.0", | ||
"private": true, | ||
"egg": { | ||
"framework": "example-framework" | ||
}, | ||
"dependencies": { | ||
"example-framework": "*" | ||
} | ||
} | ||
``` | ||
|
||
**Note:We can use `npm link` for local test before releasing the framework [npm-link](https://docs.npmjs.com/cli/link).** | ||
|
||
```bash | ||
$ cd example-app | ||
$ npm link ../egg-framework | ||
$ npm i | ||
$ npm test | ||
``` | ||
|
||
## Last | ||
|
||
In conclusion, we can see how to make the framework evolution step by step which benefits from Egg provides the powerful plugin mechanism, code co-build, reusability and modularity. | ||
|
||
|
||
- in general, put codes into `lib/plugin` if it can be reused in the application. | ||
- separate it into a `node module` when plugin becomes stable. | ||
- application with relatively reusable codes will work as a separate plugin. | ||
- abstract as framework to release after application become certain solutions of specified business scenario. | ||
- it would be a great improvement of teamwork after plugins extract, modularize and finally as a framework, beacuase other projects could reuse codes by just `npm install`. | ||
|
||
- **Note:Whether application/plugin/framework, unittest is a must and try to reach 100% coverage** |