UNPKG

8.65 kBMarkdownView Raw
1# f2e-server
2f2e-server 2
3
4## Install
5`npm i -g f2e-server`
6
7## Options
8- `f2e -h`
9- `f2e conf` 生成 .f2econfig.js 配置文件 [.f2econfig.js](.f2econfig.js) 的一个clone版本,需要自行修改
10- `f2e build` 构建到 output 目录 (需要在配置文件中配置 output 路径)
11 - `f2e build -w true` 开启构建并监听文件变化输出结果
12- `f2e start` 启动开发服务器
13- `f2e start -h`
14 - `f2e start` 从 2850 开始自增检测可以使用的PORT并启动
15 - `f2e start -c .f2econfig.js` 指定配置文件
16 - `f2e start -p 8080` 指定端口启动
17 - `sudo f2e start -p 443` 开启HTTPS支持
18 - `sudo f2e start -H mysite.local` 设置本地域名并从80端口启动
19 - `sudo f2e start -H mysite.local -p 8080` 设置本地域名并从指定端口启动
20
21## Config
22`f2e conf` 生成 [.f2econfig.js](.f2econfig.js) 配置文件
23
24### 基本配置
25
26``` javascript
27
28const path = require('path')
29const request = require('request')
30
31module.exports = {
32 // host: 'f2e.local.cn',
33 /**
34 * 不启用 host 识别,只根据端口处理
35 */
36 no_host: false,
37 // port: 2850,
38 /**
39 * 是否开启自动刷新
40 * @type {Boolean}
41 */
42 livereload: true,
43 /**
44 * 使用 less 编译为css, 使用 less 配置
45 * @type {Object}
46 */
47 useLess: {
48 compress: false
49 },
50 /**
51 * 支持babel编译 js/es/jsx, 支持 `.babelrc` 配置,
52 * @type {Object}
53 */
54 useBabel: {
55 getModuleId: pathname => pathname.replace(/\\+/g, '/'),
56 /**
57 * 支持多组babel-option 配置通过 only 参数匹配,匹配到一个,则停止
58 */
59 _rules: [
60 {
61 only: ['number.js'],
62 getModuleId: pathname => 'number',
63 }
64 ]
65 },
66 /**
67 * 是否支持 gzip
68 * @type {Boolean}
69 */
70 gzip: true,
71 /**
72 * Range 默认大小
73 * @type {Number}
74 */
75 range_size: 1024 * 1024,
76 /**
77 * 支持中间件列表, 默认添加的系统中间件后面, build之前
78 *
79 * ☆ 重要的
80 * 1. 自定义中间件中所有事件 onXxx 也支持在外面定义, 在组件内更显条理, 而且也方便自己封装插件多处引入
81 * 2. 系统中间件顺序 include(0) -> less(1) -> babel(2) ---> build(last)
82 * 3. 顶层定义的事件顺序在系统中间件之前
83 * @type {Array<Function>}
84 */
85 middlewares: [
86 // marked 编译
87 (conf) => {
88 // conf 为当前配置
89 return {
90 /**
91 *
92 * @param {string} pathname 当前资源路径
93 * @param {Request} req 原生request对象
94 * @param {Response} resp 原生response对象
95 * @param {Object} memory 所有目录对应内存结构, get/set等方法调用会被 onSet/onGet 等拦截
96 */
97 onRoute (pathname, req, resp, memory) {
98 // 搞一个代理试试
99 if (pathname.match(/^es6/)) {
100 request(pathname.replace('es6', 'http://es6.ruanyifeng.com')).pipe(resp)
101 return false
102 }
103 },
104 /**
105 *
106 * @param {string} eventType 事件类型 change/add/etc.
107 * @param {string} pathname 当前修改文件的路径
108 * @param {boolean} build 是否开启了build配置, build模式下可能同时需要触发其他资源修改等
109 */
110 buildWatcher (eventType, pathname, build) {
111 console.log(new Date().toLocaleString(), eventType, pathname)
112 },
113 /**
114 * onSet 设置资源内容时候触发
115 * @param {string} pathname 当前资源路径
116 * @param {string/Buffer} data 上一个流结束时候的数据
117 * @param {object} store 数据仓库 {_get, _set}
118 * @return {string/Buffer} 将要设置的内容
119 */
120 onSet(pathname, data, store) {
121 if (pathname.match(/\.md$/)) {
122 let res = require('marked')(data.toString())
123 // 在数据仓库中设置一个新的资源 .html
124 store._set(pathname.replace(/\.md$/, '.html'), res)
125 }
126 },
127 /**
128 * 跟onSet类似, 开发环境下面,每次请求都会执行, 缩短server启动时间可以把onSet的逻辑扔这里
129 */
130 onGet(pathname, data, store) {},
131 /**
132 * 不希望影响构建的操作, 仅在server中触发, 不希望影响构建的操作(例: 自动更新脚本插入)
133 */
134 onText(pathname, data, req, resp, memory) {},
135 buildFilter(pathname, data) {},
136 outputFilter (pathname, data) {
137 // .md 资源server环境可见, 但是不输出
138 return !/\.md$/.test(pathname)
139 }
140 }
141 },
142 // lodash 模板引擎
143 () => {
144 const _ = require('lodash')
145 return {
146 // 中间件置顶位置 include 之后
147 setBefore: 1,
148 onSet (pathname, data) {
149 // data 目录下面的文本资源需要经过模板引擎编译
150 if (pathname.match(/^test\/.*.html/)) {
151 let str = data.toString()
152 try {
153 str = _.template(str)({__dirname, require})
154 } catch (e) {
155 console.log(pathname, e)
156 }
157 return str
158 }
159 }
160 }
161 }
162 ],
163 /**
164 * 只构建指定条件的资源
165 * @param {string} pathname 资源路径名
166 * @param {Buffer/string} data 资源内容
167 * @return {Boolean}
168 */
169 buildFilter: (pathname, data) => {
170 // 路径过滤
171 let nameFilter = !pathname || /lib|test|index|README/.test(pathname)
172 // 资源大小过滤
173 let sizeFilter = !data || data.toString().length < 1024 * 1024
174 return nameFilter && sizeFilter
175 },
176 /**
177 * build 阶段是否使用 uglify/cleanCSS 进行 minify 操作
178 * @param {string} pathname 资源路径名
179 * @param {Buffer/string} data 资源内容
180 * @return {Boolean}
181 */
182 shouldUseMinify: (pathname, data) => {
183 let ok = data.toString().length < 1024 * 1024
184 !ok && console.log('shouldNotUseMinify: ' + pathname)
185 return ok
186 },
187 /**
188 * 简单资源打包方案
189 */
190 bundles: [
191 {
192 /**
193 * 满足当前正则匹配,则附加到 `pathname.replace(test, dist)` 资源
194 * 1. dist路径必须能够匹配资源否则无效
195 * 2. test匹配到的资源(除dist外), 不再输出
196 */
197 test: /bundle[\\/].*/,
198 dist: 'test.js'
199 }
200 ],
201 /**
202 * app 默认时候 f2e 构建系统, 支持 'static' 纯静态服务器
203 * 如果 app 自定义, 相当于只是使用 f2e 的端口开启和域名解析功能, 其他所有配置失效
204 */
205 // app: 'static',
206 /**
207 * 资源数据目录, 未设置的时候 build 中间件不开启
208 * @type {local-url}
209 */
210 output: path.resolve(__dirname, '../output'),
211 /**
212 * after server create
213 * you can render websocket server via this
214 */
215 onServerCreate: (server) => {
216 const { Server } = require('ws')
217 const wss = new Server({server});
218 wss.on('connection', (socket) => {
219 socket.send('init')
220 })
221 }
222}
223
224```
225
226### 中间件
227参考 [f2e-middleware](https://github.com/shy2850/f2e-middleware)
228
2291. lodash 模板引擎
2302. markdown 编译
2313. proxy 请求代理配置
2324. dest 构建资源输出重命名
2335. qrcode 简单二维码生成器
234
235### app接入
236支持接入 [Koa](http://koajs.com/) 以及 [express](https://expressjs.com/)
237
238``` javascript
239const Koa = require('koa')
240const app = new Koa()
241
242app.use(ctx => {
243 ctx.body = __dirname
244})
245
246
247const express = require('express')
248const app1 = express()
249
250app1.get('/', function (req, res) {
251 res.send(__dirname)
252})
253
254app1.use(express.static('lib'))
255
256module.exports = {
257 // app: app.callback(),
258 // app: 'static', // 纯静态资源服务器
259 app: app1
260}
261```