注释:如下内容只是『koa2-webpack-boilerplate』的说明文档,算不得一篇文章,纯粹我的的随笔记录。javascript
This is a starter koa boilerplate app I've put together using the following technologies:html
✓ koa v2
✓ webpack v3
✓ ES2015+
✓ Babel
✓ SCSS
✓ Hot reload
✓ Eslint
✓ pre-commit
✓ ...java
^6.0.0
^5.0.0
基于 koa-boilerpate
开始一个新的项目node
$ git clone git@github.com:chenbin92/koa2-webpack-boilerplate.git MyApp $ cd MyApp $ npm install # Install project dependencies listed in package.json
安装项目依赖成功后,启动开发环境命令以下jquery
// run the dev server http://localhost:3000 $ npm run dev:start
其余任务脚本webpack
npm <script> |
Description |
---|---|
star:dev |
Serves your app in development mode |
star:prod |
Serves your app in production mode |
build |
Builds the application |
lint |
Lints the project for potential errors |
通常项目结构能够按照文件类型
、功能类型
或其余类型设计,每一个团队每一个项目均可能会有本身的项目结构。 koa2-webpack-boilerplate 奉行『约定优于配置』,按照一套统一的约定进行应用开发。git
koa2-webpack-boilerpate ├── index.js # 用于自定义启动时的初始化工做(如配置babel-register) ├── src # 应用源代码 | ├── assets # 静态资源 | | ├── images | | ├── javascripts | | └── stylesheets | ├── config # 用于编写配置文件 | | └── dictionary.js | | │ ├── controller # 用于解析用户的输入,处理后返回相应的结果 │ | └── home.js │ ├── service # 用于编写业务逻辑层 │ | └── user.js │ ├── middleware # 用于编写中间件 │ | └── response_time.js │ ├── public # 惟一对外开放的文件夹,存放静态文件和编译后的资源文件 │ | └── favicon.ico │ ├── view # 用于放置模板文件 │ | └── home.html │ └── router # 用于配置 URL 路由规则 │ | └── index.js ├── build # 用于编写构建文件 | ├── chalk.config.js | ├── project.config.js | └── webpack.prod.js └── test # 用于单元测试
咱们使用 webpack 对 app/assets/*
目录下的文件进行动态编译打包至 app/public/*
目录下,经过 assetsMiddleware 中间件根据自动注入 bundle 文件。github
大体思路是:web
assets-webpack-plugin
生成 assetsMap.json
文件,而后根据 assetName
映射;ctx.state
上挂载 link
和 script
属性,用于在 index.html
引用文件ctx.state.script = (assetName) => { return `<script src='${getUrlByEnv(assetName)}'></script>`; }; ctx.state.link = (assetName) => { return `<link rel='stylesheet' href='${getUrlByEnv(assetName)}'>`; };
应用图片默认的位置是 app/assets 文件夹中的 images,经过相关配置会监听并自动将图片自动映射到 app/public 目录下;
你能够这样引用图片:
// in HTML <img src="images/egg_logo.svg" alt="logo">
// in SCSS background-image: url("images/egg_logo.svg");
推荐使用 SASS 进行样式编写;CSS 组织按照页面(page)和框架(framework)进行区分自定义的和第三方库的样式,经过 @import
导入到 application.css
,目录结构形如:
├── stylesheets | ├── page | | ├── homepage.csss | | └── help.scss | ├── framework | | ├── bootstrap.csss | | └── button.scss | ├── application.scss
应用按照功能模块化进行开发,主要有如下两种约定:
模块化的几种写法:
方式一:挂载到 window 对象
window.ModuleName = (function() { function Fn() { this.fn1(); } Fn.prototype.fn1 = function() {} return Fn })();
方式二:IIFE
window.app = window.app || {}; (function(app) { app.ModuleName = (function() { // your code... })(); }).call(window, app); // or (function(global) { class ModuleName { // your code... } global.ModuleName = ModuleName })(window.appp || (window.app = {}));
方式三:挂载到 app 对象上
class ModuleName { // your code... } window.app = window.app || {}; app.ModuleName = ModuleName;
方式四: ES6 Class
class ModuleName { constructor() {} fn() {} } export default ModuleName
在应用的 app/assets/javascripts/application.js 文件包含下面几行代码:
// import stylesheets import '../stylesheets/application.scss'; // import page scripts import './home'; import './about';
在应用的 app/assets/javascripts/vendors.js 文件包含下面几行代码:
// import Third-party libraries import $ from 'jquery'; import _ from 'lodash';
在 JavaScript 文件中,主要分为如下几个部分按照从上到下的顺序处理的:
简单演示约定
import Router from 'koa-router'; import home from '../controller/home'; import about from '../controller/about'; const appRoutes = () => { // TODO: 添加前缀会致使静态资源没法加载 const router = new Router({ prefix: '/test', }); router .get('/', home) .get('/about', about); return router; }; export default appRoutes;
项目遵循 eslint-egg
规则;在开发模式下进行 eslint watching,它能够有效的提示你对应的代码是否符合约定规则。
pre-commit
是一个 git
的勾子,它能够确保你在提交代码前须要经过你预设的相关约定;在脚手架中主要用来确保在你提交代码以前必须先经过全部的 Eslint
检查,不然不能提交。
需求:如何在一个域名下根据项目名称做为前缀,同时挂载多个 web 应用。
例如:
根域名:http://www.upchina.com/ A 应用:http://www.upchina.com/A B 应用:http://www.upchina.com/B C 应用:http://www.upchina.com/C
解决方案:经过 Mount 解决,其思想是把整个应用看成一个中间件,在 mount
内修改应用的 path
,而后再次建立一个新的应用,将 mount 中间件传递
import Koa from 'koa' import mount from 'mount' import router from 'router' // 传递给 mount const a = new Koa() a.use(router().routes()) // app const app = new Koa() app.use(mount('/m', a)) app.listen(3001)
注意