What is EggBorn. Js
Eggborn. js is a top-level Javascript full stack development framework.
Eggborn.js is a best practice for full stack development using Javascript. Eggborn.js does not repeat the wheel, but uses the industry’s latest open source technology, the best combination of full stack development. Eggborn.js uses vue.js + Framework7 / Vue Router + Webpack at the front end, koa.js + egg.js at the back end, and mysql at the database. Eggborn.js keeps track of the latest achievements of open source technology and continues to optimize to keep the framework in top shape.
What problem does Eggborn.js focus on: business modularity
The rapid development of Javascript technology has brought a smoother experience for front-end and back-end development and significantly improved development efficiency. However, some netizens still question whether Javascript is capable of developing large Web applications. Large Web applications are characterized by the need to develop a large number of page components as the business grows. Faced with this scenario, there are generally two solutions:
The disadvantage of the single-page construction method is the large deployment package generated. 2 asynchronous page loading mode, the disadvantage is that the page is too scattered, need frequent interaction with the back end.
Eggborn.js implements a third solution:
3 Page components are classified according to business requirements, modularized, and realize the asynchronous loading mechanism of modules, so as to bridge the shortcomings of the first two solutions and perfectly meet the continuous growth of large Web application business needs.
Technical characteristics of eggborn.js
- Business modularity: Page components are organized by modules
- Flexible loading mode: modules can be loaded asynchronously or synchronously
- Modules are highly cohesive: Modules include front-end page components and back-end business logic
- Flexible parameter configuration: The front and back ends of a module can be configured independently
- Internationalization: Both the front and back ends of the module support independent internationalization
- Module isolation: The page, data, logic, routing, configuration and other elements of a module are namespace isolated to avoid variable pollution and conflict between modules
- Super easy transaction processing: just configure a parameter on the routing record, you can perfect the transaction processing of the database.
- Progressive development: Due to the highly cohesive nature of modules, business can be deposited as modules that can be reused in multiple projects, either contributed to the NPM open source community or deployed to a company’s private NPM repository.
With eggborn.js, you can reuse not only components, but also business modules.
Quick learning
Install eggborn.js scaffolding
$ npm install -g egg-bornCopy the code
New project
$ egg-born project_name
$ cd project_name
$ npm installCopy the code
Eggborn.js currently provides 2 project scaffolding, respectively
front-backend-mysql
Back-end full stack project templatefront
— Front-end project template, back-end can adopt other schemes
Configure mysql connection parameters
If front-backend-mysql is used, configure mysql connection parameters (empty database).
Edit the SRC/backend/config/config. The default. Js file
// mysql
config.mysql = {
clients: {
// donot change the name
__ebdb: {
host: '127.0.0.1'.port: '3306'.user: 'travis'.password: ' '.database: 'egg-born',}}};Copy the code
Run the project
Start the back-end service
$ npm run dev:backendCopy the code
Start the front-end service
$ npm run dev:frontCopy the code
EggBorn. Js architecture diagram
System architecture
Project file structure
Module file structure
Module development
Naming conventions
In order to continuously precipitate service modules and achieve a highly reusable effect, the namespace of all modules must be fully isolated to avoid mutual pollution and conflict, so the following naming method is adopted:
egg-born-module-{providerId}-{moduleName}
For example, the module egg-born-module-a-version is named as follows:
providerId
: amoduleName
: versionfullName
: egg-born-module-a-versionrelativeName
: a-version- Front-end page routing address: /a/version/{page}
- /a/version/{controller}/{action}
Loading mechanism
The module supports both asynchronous and synchronous loading. The default is asynchronous loading. To load the module synchronously, add the -sync suffix to the module name, for example, egg-born-module-aa-login-sync.
The new module
Go to the SRC/Module directory and execute the scaffolding to create the module file skeleton
$ egg-born module_relative_nameCopy the code
Eggborn.js currently provides 2 modular scaffoldings, respectively
module
Full stack module templatemodule-front
Front-end module template
Module front-end development
Front-end page routing
Add a page route to front/ SRC /routes.js, as shown in the following example
function load(name) {
return require(`./pages/${name}.vue`).default;
}
export default[{path: 'welcome/:who'.component: load('welcome')}, {path: 'profile'.component: load('profile'), meta: { requiresAuth: true}}, {path: '/login'.component: load('login')},];Copy the code
path
: Path. Parameters are supported. In order to/
Beginning, representing the root page component.login
Page components are typically configured this waycomponent
: page component objectmeta
: Route metadatameta.requiresAuth
: If the page component requires login, set this parameter totrue
To reference a page component in a page, use an absolute path, such as
<f7-list-item link="/aa/hello/welcome/You" title="Welcome"></f7-list-item>
<f7-list-item link="/aa/hello/profile" title="Profile"></f7-list-item>Copy the code
Front-end state Management
Vuex is a state management mode developed specifically for vue.js applications. Eggborn. js implements a completely isolated module state management mechanism using Vuex. Add state in front/ SRC /store.js, as in
export default function(Vue) {
return {
state: {
message: 'hello world',}}; }Copy the code
Access the module state in the page component
const message = this.$local.state.message;Copy the code
Access other module states in page components
const message = this.$store.state[providerId][moduleName].message;Copy the code
For more information, see: Vuex
Front-end Parameter Configuration
In front/SRC/config/config. Js add configuration information, such as
export default {
mode: 1};Copy the code
You can only access the internal parameters of the module from the page component
const mode = this.$config.mode;Copy the code
Front-end internationalization
The following is an example of adding the language definition in the internationalization file zh-cn.js in the front/ SRC /config/locale directory
export default {
mode: 'model'."Hello world! I'm %s.": 'Hello, world! I am a % s. '};Copy the code
The internationalization language adopts the global merge mode, which is conducive to the sharing of language resources. The page component can be accessed as follows
const mode = this.$text('mode');
const message = this.$text("Hello world! I'm %s.".'zhennann');Copy the code
Module backend development
Back-end API routing
Add API routes to backend/ SRC /routes.js, for example
const home = require('./controller/home.js');
module.exports = [
{ method: 'get'.path: 'home/index'.controller: home, action: 'index'.transaction: true},];Copy the code
method
: Get/POSTpath
: Path. Parameters are supportedcomponent
: the Controller objectaction
: Controller method. If this is not set, the path suffix word is automatically usedtransaction
: Defaults to false. If set to true, database transactions are enabled
Access the module API route in the front-end page component
this.$api.get('home/index').then(data= > {
}).catch(err= >{});Copy the code
Access other module API routes in front page components
this.$api.get('/providerId/moduleName/home/index').then(data= > {
}).catch(err= >{});Copy the code
The back-end Controller
Back-end controllers are implemented in the same way as egg.js
module.exports = app= > {
class HomeController extends app.Controller {
async index() {
const message = await this.service.home.index();
this.ctx.success(message); }}return HomeController;
};Copy the code
For more information, see: egg.js Controller
The back-end Service
Service encapsulates the business logic to be invoked by the Controller in the same way as egg.js.
module.exports = app= > {
class Home extends app.Service {
async index() {
const res = await this.ctx.db.queryOne('show tables');
returnres; }}return Home;
};Copy the code
Unlike egg.js, the Service operates on the database using ctx.db, which automatically supports database transactions.
For more information, see egg.js Service
Backend Controller call
To support the development of large Web systems, eggborn.js supports calls between module back-end controllers, such as
const message = await this.ctx.performAction({
method: 'get'.url: 'home/index'.query: {
username: 'kevin',},params: {
mode: 1,},body: {
content: 'ready',}});Copy the code
method
: Get/POSTurl
: Controllers accessing this module use relative paths, while controllers accessing other modules use/
The absolute path at the beginning.query
,params
,body
: Consistent with regular Controller parameters
Back-end database operations
Back-end database operations are consistent with egg.js
For more information, see: egg.js MySQL
Back-end database transactions
Eggborn.js provides a more convenient way to implement database transactions by configuring transaction parameters in the back-end API routing record, and the Service uses CTx.db to operate on the database. If the master Controller calls the child Controller through ctx.performAction, the database transaction start rule is as follows:
The main Controller configuration | The child Controller configuration | The child Controller is actually enabled |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
Configure back-end parameters
In the backend/SRC/config/config. Js add configuration information, such as
module.exports = appInfo= > {
const config = {};
config.message = "Hello world! I'm %s.";
return config;
};Copy the code
The following is an example of how to access this module
const message = this.ctx.config.message;Copy the code
Back-end internationalization
In the backend/SRC/config/locales directory add internationalization files useful – cn. Language definition of js file example below
module.exports = {
"Hello world! I'm %s.": 'Hello, world! I am a % s. '.'not found': 'Not found'};Copy the code
The internationalization language adopts the global merge mode to facilitate the sharing of language resources. The access mode is as follows
const notFound = this.ctx.text('not found');
const message = this.ctx.text("Hello world! I'm %s.".'zhennann');Copy the code
Backend error handling
In the backend/SRC/config/errors. Js file to add the error code
// error code should start from 1001
module.exports = {
1001: 'not found'};Copy the code
The following is an example of an error message
this.ctx.fail(1001);Copy the code
The following is an example of an exception that can be thrown
this.ctx.throw(1001);Copy the code
Module management
Module is dependent on
Eggborn.js manages module dependencies through the package.json file. For example, module AA-Module1 depends on Module AA-Module2. You need to perform the following configuration in the package.json file of module AA-Module1
{
"name": "egg-born-module-aa-module1"."version": "0.0.1"."eggBornModule": {
"dependencies": {
"aa-module2": "0.0.1"}},"dependencies": {
"egg-born-module-aa-module2": "^ 0.0.1." "}}Copy the code
“Egg-born-module-aa-module2 “: “^0.0.1” is set to automatically install module AA-module2 when module AA-Module1 is installed. This is not necessary if the module is not published publicly.
Module data version
Modules typically operate on databases, and the database structure may change when the template version is updated. Eggborn. js implements module data version management, facilitating the accumulation and precipitation of service modules.
Set fileVersion to the current data version in the module’s package.json file
{
"name": "egg-born-module-aa-module1"."version": "0.0.1"."eggBornModule": {
"fileVersion": 1}}Copy the code
Add an Api route at the back end of the module
{ method: 'post'.path: 'version/update'.controller: version }Copy the code
Add the version Controller
module.exports = app= > {
class VersionController extends app.Controller {
async update() {
await this.service.version.update(this.ctx.getInt('version'));
this.ctx.success(); }}return VersionController;
};Copy the code
Add the version Service
module.exports = app= > {
class Version extends app.Service {
async update(version) {
if (version === 1) {
// do something}}}return Version;
};Copy the code
When the back-end service is started, eggborn.js automatically detects the data version change of the module and executes the corresponding route to complete the data version upgrade.
Module to release
When the module code in the project is stable, the module can be published and contributed to the open source community. It is also possible to set up a private NPM repository within the company and then publish the modules to a private repository to form corporate assets for easy reuse. The module publishing steps are as follows
$ cdPath /to/module -- Go to the module directory $NPM install -- Install module dependencies $NPM run build:front -- Build front-end code $NPM run build: Backend -- build back-end code $NPM Publish -- Publish to the NPM repositoryCopy the code
Test drive
Currently, only back-end test drivers are supported
Back-end Controller tests
Add the Controller test file in the Backend /test/ Controller directory
// controller/home.test.js
const { app, mock, assert } = require('egg-mock/bootstrap');
const parseMockUrl = function(url) {
const prefix = app.mockUtil.parseUrlFromPackage(__dirname);
return `${prefix}${url}`;
};
describe('test/controller/home.test.js', () => {
it('action:index'.async() = > {const result = await app.httpRequest().get(parseMockUrl('home/index'));
assert(result.body.code === 0);
});
});Copy the code
Back-end Service testing
Add the service test file in the backend/test/service directory
// service/home.test.js
const { app, mock, assert } = require('egg-mock/bootstrap');
const parseMockUrl = function() {
return app.mockUtil.parseUrlFromPackage(__dirname);
};
describe('test/service/home.test.js', () => {
it('index'.async() = > {const ctx = app.mockContext({ mockUrl: parseMockUrl() });
const message = await ctx.service.home.index();
assert(message);
});
});Copy the code
Perform the test
Perform the tests in the project root directory
$ npm run test:backend
$ npm run cov:backendCopy the code
Front-end Architecture Configuration
Front-end startup file
The front-end architecture offers two solutions
- Vue.js + Framework7
- Vue.js + Vue Router
Framework7 is a mobile development-specific UI library with built-in routing mechanisms. The Vue Router is the official vue. js routing library. You can use the Vue Router with other UI libraries.
Switch in SRC /front/main.js
// choose one
// framework7
import main from './framework7/main.js';
// vuerouter
// import main from './vuerouter/main.js';
// export
export default main;Copy the code
Front-end Parameter Configuration
SRC/front/config/config. Js files can override the parameters in the configuration module parameters
export default{
module: {
'aa-hello': {
mode: 2,}}};Copy the code
Front-end internationalization
Add the internationalization file in the SRC /front/config/locale directory to override the language definition in the module’s internationalization language zh-cn.js file
export default {
mode: 'model'};Copy the code
Back-end architecture configuration
The backend architecture
The back-end architecture is based on egg.js and fully supports all functions and features provided by egg.js
For more information, see: egg.js
Configure back-end parameters
SRC/backend/config/config. Default. Js files can override the parameters in the configuration module parameters
module.exports = appInfo= > {
const config = {};
// module config
config.module = {
'aa-hello': {
mode: 2,}};return config;
};Copy the code
Back-end internationalization
In SRC/backend/config/locales directory add internationalization files, you can override the module international language useful – cn. Language definition of js file example below
module.exports = {
mode: 'model'};Copy the code
Project deployment
Build front-end code
$ npm run build:frontCopy the code
Start the back-end service
$ npm run start:backendCopy the code
Stop back-end services
$ npm run stop:backendCopy the code
Configure back-end service startup parameters
Edit the build/config.js file
// backend
const backend = {
port: 7002.hostname: '127.0.0.1'};Copy the code
Nginx configuration
It is strongly recommended to use Nginx to host front-end static resources and reverse proxy back-end services as follows
server {
listen 80;
server_name example.com www.example.com;
set $node_port 7002;
root /path/to/www;
location /api/ {
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http:/ / 127.0.0.1: $$request_uri node_port;proxy_redirect off; }}Copy the code
Making contribution
If you have any questions, please submit the issue, or directly modify and submit PR!