Overview
A server library tries to understand what developers really need.
The philosophy behind NoBone is providing possibilities rather than telling developers what they should do. All the default behaviors are just examples of how to use NoBone. All the APIs should work together without pain.
Features
- Code you program, not configure.
- Built for performance.
- Not only a good dev-tool, but also good at production.
- Supports programmable plugins.
- Cross platform.
- Pure js, supports coffee by default.
Install
Install as an dependency:
npm install nobone # View a better nobone documentation than Github readme. node_modules/.bin/nobone --doc
Or you can install it globally:
npm i -g nobone # View a better nobone documentation than Github readme. nb -d
FAQ
- Why doesn't the auto-reaload work?
Check if the
process.env.NODE_ENV
is set todevelopment
.
- Why doesn't the compiler work properly?
Please delete the
.nobone
cache directory, and try again.
- How to view the documentation with TOC (table of contents) or offline?
If you have installed nobone globally, just execute
nobone --doc
ornobone -d
. If you are on Windows or Mac, it will auto open the documentation.
If you have installed nobone with
npm install nobone
in current directory, executenode_modules/.bin/nobone -d
.
- Why I can't execute the entrance file with nobone cli tool?
Don't execute
nobone
with a directory path when you want to start it with an entrance file.
- When serving
jade
orless
, it doesn't work.
These are optinal packages, you have to install them first. For example, if you want nobone to support
jade
, please executenpm install -g jade
.
- How to disable that annoying nobone update warn?
There's an option to do this:
nb = nobone null, { checkUpgrade: false }
.
Quick Start
process.env.NODE_ENV = 'development' nobone = require 'nobone' port = 8219 # If you want to init without a specific module, # for example 'db' and 'service' module, just exclude them: # nobone { # renderer: {} # } # By default it only loads two modules: `service` and `renderer`. nb = nobone db: dbPath: './test.db' proxy: renderer: service: lang: langPath: 'examples/fixtures/lang' current: 'cn' # Service nbserviceget '/' # Renderer # It will auto-find the 'examples/fixtures/index.tpl', and render it to html. # You can also render jade, coffee, stylus, less, sass,markdown, # or define custom handlers. # When you modify the `examples/fixtures/index.tpl`, the page will auto-reload. nbrendererrender'examples/fixtures/index.html' then ressend tplFn name: 'nobone' # Launch express.js nbservicelisten port-> # Kit # A smarter log helper. nbkitlog 'Listen port ' + port # Open default browser. nbkitxopen 'http://127.0.0.1:' + port # Static folder for auto-service of coffeescript and stylus, etc. nbserviceuse nbrendererstatic'examples/fixtures' # Database # Nobone has a build-in file database. # Here we save 'a' as value 1. nbdbloadedthen -> nbdbexec db.doc.a = 1 dbsave'DB OK' then nbkitlog data # Get data 'a'. nbkitlog nbdbdoca # Proxy # Proxy path to specific url. nbserviceget '/proxy.*' # If you visit "http://127.0.0.1:8013/proxy.js", # it'll return the "http://127.0.0.1:8013/main.js" from the remote server, # though here we just use a local server for test. nbproxyurl reqres"http://127.0.0.1:/main." + reqparams0 # Globalization nbkitlog 'human'l # -> '人类' nbkitlog 'open|formal'l # -> '开启' nbkitlog nblang'find %s men'10'jp' # -> '10人が見付かる' = -> # Release all the resources. nbclosethen -> nbkitlog 'Peacefully closed.'
Tutorials
Code Examples
See the examples.
CLI Usage
You can use nobone as an alternative of node
bin or coffee
, it will auto detect file type and run it properly.
Run Script
Such as nb app.js
, nb app.coffee
. It will run the script and if
the script changed, it will automatically restart it.
You can use nb -w off app.js
to turn off the watcher.
You can pass a json to the watch list nb -w '["a.js", "b.js"]' app.js
.
Any of watched file changed, the program will be restarted.
Static Folder Server
Such as nb /home/
, it will open a web server for you to browse the folder content. As you edit the html file in the folder, nobone will live
reload the content for you. For css or image file change, it won't refresh the whole page, only js file change will trigger the page reload.
You can use url query ?source
and url hash #L
to view a source file.
Such as http://127.0.0.1:8013/app.js?source#L10
,
it will open a html page with syntax highlight.
Or full version http://127.0.0.1:8013/app.js?source=javascript#L10
You can use ?gotoDoc
to open a dependencies' markdown file. Such as jdb/readme.md?gotoDoc
. Nobone will use the node require's algorithm to search for the module recursively.
CLI
Install nobone globally: npm install -g nobone
nb
# Help info nb -h # Use it as a static file server for current directory. # Visit 'http://127.0.0.1/nobone' to see a better nobone documentation. nb # Use regex to filter the log info. # Print out all the log if it contains '.ejs' logReg='.ejs' nb # Use custom logic to start up. nb app.jswatchPersistent=off nb app.js # Scaffolding helper nb bone -h
no
This command is inherited from the nokit
's.
For more information:
# Run default task no # See help no -h
Plugin
Here I give a simple instruction. For a real example, see nobone-sync.
Package config
NoBone support a simple way to implement npm plugin. And your npm package doesn't have to waist time to install nobone dependencies. The package.json
file can only have these properties:
"name": "nobone-sample" "version": "0.0.1" "description": "A sample nobone plugin." "main": "main.coffee"
The name
of the plugin should prefixed with nobone-
.
Main Entrance File
The main.coffee
file may looks like:
require 'nobone'kitlog 'sample plugin'
Use A Plugin
Suppose we have published the nobone-sampe
plugin with npm.
Other people can use the plugin after installing it with either npm install nobone-sample
or npm install -g nobone-sample
.
To run the plugin simply use nobone sample
.
You can use nb ls
to list all installed plugins.
Modules API
It's highly recommended reading the API doc locally by command nb --doc
nobone
-
#### Overview
NoBone has several modules and a helper lib. All the modules are optional. Only the
kit
lib is loaded by default and is not optional.Most of the async functions are implemented with Promise.
-
Main constructor.
-
param:
modules
{ Object }By default, it only load two modules,
service
andrenderer
:service:renderer:db: nullproxy: nulllang: nulllangPath: null # language set directory -
param:
opts
{ Object }Defaults:
# Whether to auto-check the version of nobone.checkUpgrade: true# Whether to enable the sse live reload.autoReload: true -
return: { Object }
A nobone instance.
-
-
#### close()
Release the resources.
- return: { Promise }
-
#### version()
Get current nobone version string.
- return: { String }
-
#### checkUpgrade()
Check if nobone need to be upgraded.
- return: { Promise }
-
#### client(opts, useJs)
The NoBone client helper.
-
static:
-
param:
opts
{ Object }The options of the client, defaults:
autoReload: kitisDevelopmenthost: '' # The host of the event source. -
param:
useJs
{ Boolean }By default use html. Default is false.
-
return: { String }
The code of client helper.
-
example:
When the client code is loaded on the browser, you can use the
nokit.log
to log anything to server's terminal. Nobone server will auto-format and log the information to the terminal. It's convinient for mobile development when remote debug is not possible.# The nokit is assigned to the "window" object.nokitlog a: 10nokitlog 10
-
kit
-
#### Overview
A collection of commonly used functions.
service
-
#### Overview
It is just a Express.js wrap.
-
extends: { Express }
-
-
#### service(opts)
Create a Service instance.
-
param:
opts
{ Object }Defaults:
autoLog: kitisDevelopmentenableSse: kitisDevelopmentexpress:sse: -
return: { Service }
-
-
#### server
The server object of the express object.
-
type: { http.Server }
-
renderer
-
#### Overview
An abstract renderer for any content, such as source code or image files. It automatically uses high performance memory cache. This renderer helps nobone to build a passive compilation architecture. You can run the benchmark to see the what differences it makes. Even for huge project the memory usage is negligible.
-
extends: { events.EventEmitter }
-
-
#### renderer(opts)
Create a Renderer instance.
-
param:
opts
{ Object }Defaults:
enableWatcher: kitisDevelopmentautoLog: kitisDevelopment# If renderer detects this pattern, it will auto-inject `noboneClient.js`# into the page.injectClientReg: /<html[^<>]*>[\s\S]*</html>/icacheDir: '.nobone/rendererCache'cacheLimit: 1024fileHandlers:'.html':default: trueextSrc: '.tpl''.ejs''.jade'# Extra files to watch.extraWatch: path1: 'comment1'path2: 'comment2'...encoding: 'utf8' # optional, default is 'utf8'dependencyReg:'.ejs': /<%[\n\r\s]*include\s+\s*%>/g: ...# Simple coffee compiler'.js':extSrc: '.coffee': ...# Browserify a main entrance file.'.jsb':type: '.js'extSrc: '.coffee'dependencyReg: /require\s+/g: ...'.css':extSrc: '.styl''.less''.sass''.scss': ...'.md':type: 'html' # Force type, optional.extSrc: '.md''.markdown': ... -
return: { Renderer }
-
-
#### fileHandlers
You can access all the fileHandlers here. Manipulate them at runtime.
-
type: { Object }
-
example:
nobonerendererfileHandlers'.css'compiler =stylus = kitrequireOptional 'stylus'__dirnamecompile = stylusstrdataset 'filename'path# Take advantage of the syntax parser.this.dependencyPaths = compiledepskitpromisifycompilerendercompile
-
-
#### cachePool
The cache pool of the result of
fileHandlers.compiler
-
type: { Object }
Key is the file path.
-
-
#### dir(opts)
Set a service for listing directory content, similar with the
serve-index
project.-
param:
opts
{ String | Object }If it's a string it represents the rootDir.
-
return: { Middleware }
Experss.js middleware.
-
-
#### static(opts)
Set a static directory proxy. Automatically compile, cache and serve source files for both deveopment and production.
-
param:
opts
{ String | Object }If it's a string it represents the rootDir. of this static directory. Defaults:
rootDir: '.'# Whether enable serve direcotry index.index: kitisDevelopmentinjectClient: kitisDevelopment# Useful when mapping a normal path to a hashed file.# Such as map 'lib/main.js' to 'lib/main-jk2x.js'.reqPathHandler: decodeURIComponent# Check path such as '../../../../etc/passwd'.: -> -
return: { Middleware }
Experss.js middleware.
-
-
#### staticEx(opts)
An extra version of
renderer.static
. Better support for markdown and source file.-
param:
opts
{ String | Object }If it's a string it represents the rootDir. of this static directory. Defaults:
rootDir: '.'# Whether enable serve direcotry index.index: kitisDevelopmentinjectClient: kitisDevelopment# Useful when mapping a normal path to a hashed file.# Such as map 'lib/main.js' to 'lib/main-jk2x.js'.reqPathHandler: decodeURIComponent -
return: { Middleware }
Experss.js middleware.
-
-
#### render(path, ext, data, isCache, reqPath, handler)
Render a file. It will auto-detect the file extension and choose the right compiler to handle the content.
-
param:
path
{ String | Object }The file path. The path extension should be the same with the compiled result file. If it's an object, it can contain any number of following params.
-
param:
ext
{ String }Force the extension. Optional.
-
param:
data
{ Object }Extra data you want to send to the compiler. Optional.
-
param:
isCache
{ Boolean }Whether to cache the result, default is true. Optional.
-
param:
reqPath
{ String }The http request path. Support it will make auto-reload more efficient.
-
param:
handler
{ FileHandler }A custom file handler.
-
return: { Promise }
Contains the compiled content.
-
example:
# The 'a.ejs' file may not exists, it will auto-compile# the 'a.ejs' or 'a.html' to html.rendererrender'a.html'then kitloghtml# if the content of 'a.ejs' is '<% var a = 10 %><%= a %>'rendererrender'a.ejs''.html'then html == '10'rendererrender'a.ejs'then str == '<% var a = 10 %><%= a %>'
-
-
#### close
Release the resources.
-
#### releaseCache(path)
Release memory cache of a file.
- param:
path
{ String }
- param:
-
#### e.compiled(path, content, handler)
-
event: { compiled }
-
param:
path
{ String }The compiled file.
-
param:
content
{ String }Compiled content.
-
param:
handler
{ FileHandler }The current file handler.
-
-
#### e.compileError(path, err)
-
event: { compileError }
-
param:
path
{ String }The error file.
-
param:
err
{ Error }The error info.
-
-
#### e.watchFile(path, curr, prev)
-
event: { watchFile }
-
param:
path
{ String }The path of the file.
-
param:
curr
{ fs.Stats }Current state.
-
param:
prev
{ fs.Stats }Previous state.
-
-
#### e.fileDeleted(path)
-
event: { fileDeleted }
-
param:
path
{ String }The path of the file.
-
-
#### e.fileModified(path)
-
event: { fileModified }
-
param:
path
{ String }The path of the file.
-
-
#### getCache(handler)
Set handler cache.
-
param:
handler
{ FileHandler } -
return: { Promise }
-
-
#### genHandler(path, handler)
Generate a file handler.
-
param:
path
{ String } -
param:
handler
{ FileHandler } -
return: { FileHandler }
-
rendererWidgets
-
#### Overview
It use the renderer module to create some handy functions.
-
#### compiler(str, path, data)
The compiler can handle any type of file.
-
context: { FileHandler }
Properties:
ext: String # The current file's extension.opts: Object # The current options of renderer.# The file dependencies of current file.# If you set it in the `compiler`, the `dependencyReg`# and `dependencyRoots` should be left undefined.dependencyPaths: Array# The regex to match dependency path. Regex or Table.dependencyReg: RegExp# The root directories for searching dependencies.dependencyRoots: Array# The source map informantion.# If you need source map support, the `sourceMap`property# must be set during the compile process.# If you use inline source map, this property shouldn't be set.sourceMap: String or Object -
param:
str
{ String }Source content.
-
param:
path
{ String }For debug info.
-
param:
data
{ Any }The data sent from the
render
function. when you call therender
directly. Default is an object:_: lodashinjectClient: kitisDevelopment -
return: { Promise }
Promise that contains the compiled content.
-
-
#### dir(opts)
Folder middleware.
-
param:
opts
{ Object } -
return: { Function }
-
-
Static middleware.
-
param:
renderer
{ Renderer } -
param:
opts
{ Object } -
return: { Function }
-
-
Static middleware. Don't use it in production.
-
param:
renderer
{ Renderer } -
param:
opts
{ Object } -
return: { Function }
-
db
-
#### Overview
See my jdb project.
-
#### db(opts)
Create a JDB instance.
-
param:
opts
{ Object }Defaults:
dbPath: './nobone.db' -
return: { Jdb }
-
-
#### jdb.loaded
A promise object that help you to detect when the db is totally loaded.
- type: { Promise }
proxy
-
#### Overview
See the proxy of nokit https://github.com/ysmood/nokit#proxy-1
-
#### proxy()
Create a Proxy instance.
- return: { Proxy }
lang
-
#### Overview
An string helper for globalization.
-
It will find the right
key/value
pair in your definedlangSet
. If it cannot find the one, it will output the key directly.-
param:
cmd
{ String }The original text.
-
param:
args
{ Array }The arguments for string format. Optional.
-
param:
name
{ String }The target language name. Optional.
-
return: { String }
-
example:
require'nobone'lang:lang.langSet =human:cn: '人类'jp: '人間'open:cn:formal: '开启' # Formal way to say 'open'casual: '打开' # Casual way to say 'open''find %s men': '%s人が見付かる'lang'human''cn'langSet # -> '人类'lang'open|casual''cn'langSet # -> '打开'lang'find %s men'10'jp'langSet # -> '10人が見付かる' -
example:
require'nobone'lang: langPath: 'lang.coffee'current: 'cn''human'l # '人类''Good weather.'lang'jp' # '日和。'lang.current = 'en''human'l # 'human''Good weather.'lang'jp' # 'Good weather.'
-
-
#### langSet
Language collections.
-
type: { Object }
-
example:
require'nobone'lang:lang.langSet ='cn': 'human': '人类'
-
-
#### current
Current default language.
-
type: { String }
-
default:
'en'
-
-
#### load(filePath)
Load language set and save them into the
langSet
. Besides, it will also add propertiesl
andlang
toString.prototype
.-
param:
filePath
{ String }js or coffee files.
-
example:
require'nobone'lang:langload 'assets/lang'lang.current = 'cn'log 'test'l # -> '测试'.log '%s persons'lang10 # -> '10 persons'
-
Changelog
See the doc/changelog.md file.
Unit Test
npm test
Benchmark
Goto see benchmark
Road Map
Decouple libs.
Better test coverage.
Lisence
BSD
May 2014, Yad Smood