Progressive Development

Egg provides both Plugin and Framework, and the former has two loading modes which are 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.

# Getting Started

Assume that we are writing a code to analyze UA to implement the function below:

You can easily write it down after previous tutorials, let's have a quick review:

Codes refer to step1.

Directory structure:

example-app
├── app
│ ├── extend
│ │ └── context.js
│ └── router.js
├── test
│ └── index.test.js
└── package.json

Core code:

// 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 be perfect at the beginning, it might be difficult to maintain if encapsulated into a plugin directly.

We can write the code as the format of plugin, but not separate out.

Codes refer to step2.

New directory structure:

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:

{
"eggPlugin": {
"name": "ua"
}
}
// config/plugin.js
const path = require('path');
exports.ua = {
enable: true,
path: path.join(__dirname, '../lib/plugin/egg-ua'),
};

# Extract to Independent Plugin

The functions of module become 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 Development.

Directory structure:

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.

Then modify the application, details refer to step3/example-app.

// 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.

$ 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 find that most of our team projects are using them.

At that time, you can consider abstracting them as a framework which is suitable for business scenarios.

Firstly, abstract the example-framework as below. Let's have a quick review, details refer to Framework.

Directory structure:

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

Then modify the application, details refer to step4/example-app.

{
"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.

$ cd example-app
$ npm link ../egg-framework
$ npm i
$ npm test

# Write in the end

In conclusion, we can see how to make the framework evolution step by step which benefits from Egg's powerful plugin mechanism, code co-build, reusability and modularity.