November's Paddleball Marathon

    node-cube

    3.2.0 • Public • Published

    Cube

    logo

    模块化你的前端代码,像node.js一样编写模块。

    Cube管理着前端三种类型的资源:

    • script js/coffee/jsx/...
    • style css/stylus/less/...
    • template html/ejs/jade/...

    Build Status NPM version

    Install

    npm install -g node-cube

    安装完成之后,命令行增加一个命令 cube

    clone本工程到本地

    cd cube
    cube start example
    

    cube的样板工程就启动了,example中有cube支持的功能测试case 也是web页面侧的测试用例

    Getting Start (6 steps)

    1. 初始化cube:

    在node工程的root目录下,安装node-cube:

    > npm install -D node-cube
    1. 在server中挂载cube middleware
    const app = require('express')();
    const Cube = require('node-cube');
    let cubeM = Cube.middleware({
      root: path.join(__dirname, '../assets')
    });
    app.use('/assets', cubeM);
    

    cubeM支持静态服务,所以设置完之后,整个assets目录即可被访问。

    1. 初始化前端html(通常在node后端模板中)
    <!-- cube.js由cubeM中间件提供,是个虚拟文件,assets目录下没有,也无需有;cube build时会自动生成 -->
    <script src='/assets/cube.js'></script>
    <script>
      /** init cube, tell cube where to load modules */
      Cube.init({
        base: '/assets',
        debug: true,
        version: 12345
      });
      /** 
       * start loading main.js and run it
       * 下面的use方法将根据上面初始化设置的base作为根地址,加载所有依赖的文件
       *  '/main.js' 意味着访问到 assets/main.js
       */
      Cube.use('/main.js', function (App) {
        console.log(App.run({
          /** config object here */
        }));
      });
    </script>
    
    1. 配置cube支持前端的各种脚本编译方式

    cube有很多种配置方式,但是推荐使用如下方式:在assets/package.json中编写配置项

    assets/package.json通常管理着前端的所有依赖,配置在cube段的config,在cube开发模式和cube build时都会来读取这份配置,配置在此可以保证build的时候和开发模式配置一致。

    {
      "cube": {
        "moduleMap": {
          /**
           * 有些编译好的模块,可以通过映射来加速
           */
          "react": "dist/react.js",
          "modulemap": "lib/index.js"
        },
        "processors": {
          ".less": "cube-less",
          /**
           * 支持本地自定义processor, 其路径可以是相对路径(相对package.json的路径)
           * 也可以是绝对路径
           */
          ".tpl": "../custom_processor",
          /**
           * 支持配置process参数
           */
          ".jsx": [
            ["cube-babel", {}]
          ],
        }
      },
      ignoreRules: []
    }
    

    其中:

    • moduleMap 为一些已经build成single-file的模块提供filemap,以加速加载
    • processors 对象定义各种文件的处理器
    • ignoreRules 中定义build时的忽略规则,和.cubeignore功能类似
    • export 定义需要被导出的文件,补充自动识别导出文件的不足

    ok, 到此cube初始化完毕,可以像编写node.js一样编写前端代码了。

    1. 编写前端代码
    // main.js
    var cookie = require('cookie');
    var tpl = require('./test.html');
    
    function  init() {
      // init layout
      $('body .main').html(tpl());
      // get nick
      var nick = cookie.get('nick');
      if (!nick) {
        nick = 'guest';
      }
      $('.node-nick').text(nick);
    }
    init();
    // 异步加载css
    load('../css/module.css', nameSpace); // namespace [optional]: prefix for css selector

    ok,一个很简单的一个模块,index.html加载了main.js,便开始执行:设置头部用户登录昵称

    Cube的模块加载是支持像node一样寻址node_modules目录的,在wwwroot目录下安装模块,可以被直接require使用, 所以可以把稳定的代码模块,发布到npm仓库实现代码复用

    引用现有的包, 你只需要

    • 编写好package依赖
    • npm install 注意这里的npm install是安装在静态资源目录,不是工程根目录。
    • 像node一样引用这些模块

    注意node_modules,虽然和node.js的模块一模一样使用,但是它们安装在不同的地方。 前端工程里使用到的模块,需要安装在静态资源目录下,如下结构:

    /project
            /assets
                  /node_modules   # client side node_modules
                  /common
                  /css
                  - package.json  # 前端所依赖的模块声明
            /lib
            /controller
            /node_modules         # server side node_modules
            - package.json        # 后端所依赖的模块申明
    1. build代码, release成静态代码

    完成开发之后,模块都会被预编译、压缩成一个个小文件,合并,然后发布到线上(cdn服务器、云存储 或 其他)

    cube提供build命名来方便的完成这一任务

    # build static folder
    cube build $resource_path -o $resource_path.release --smart --mangle-file-name

    cube build的参数:

        -h, --help             output usage information
        -o, --output [value]   set the output dir
        --output-file [value]  set the output file
        -b, --base [value]     the http base for resouce 
        -r, --root [value]     setup project base dir, the root
        --remote [value]       set the namespace for remote call
        --export [value]       files will be exported, do not merge, example: /a.js,/b.js
        --mangle-file-name     mangle the file name into random name
        --without-compress     do not compress code
        --without-wrap         do not wraper code
        --smart                smart build, only build necessary files
    

    在静态资源目录下,编写 .cubeignore来排除不需要被处理的文件,格式和.gitignore类似:

    [skip]
    /node_modules/jquery/jquery.min.js
    [ignore]
    /node_modules/.bin
    
    • 匹配skip段的文件,将跳过编译,直接copy到目标目录
    • 匹配ignore段的文件,将直接忽略,build之后不会出现在目标目录中

    不添加标记的时候,默认都为skip, 例如:

    /test/
    

    cube 在build的时候将直接copy文件,而不会build代码

    .cubeignore 文件的寻址 会从build目录开始逐级往上寻找,直到找到为止

    浏览器端API

    /**
     * 开启debug模式, 会打印模块加载调试信息
     * @static
     */
    Cube.debug();
    
    /**
     * 初始化
     * @static
     * @param options {Object}
     *   charset {String} script标签
     *   base {String} 服务器端模块的http前缀地址
     *   debug {Boolean} 是否开启debug
     *   version {Number} 静态资源版本号,刷缓存用
     *   timeout {Number} 加载脚本超时时间
     *   remoteBase:{Object} 远程模块库映射
     */
    Cube.init(options);
    
    /**
     * 异步加载模块,带回调,页面的主入口一般就这个写法
     * @static
     * 注意module传入的寻址规则, 以下规则等效,都是基于 base 根目录下
     *    /app.js
     *    ./app.js
     *    app.js
     */
    Cube.use(module, cb);
    Cube.use([mod1, mod2], function(mod1, mod2) {
      // TODO: your code here
    });
    
    /**
     * 注册页面已通过script标签加载过的模块,避免重复加载
     * @static
     * 如下,注册 jquery, lodash
     * 注意后端assets目录下,请不要安装这些模块
     */
    Cube.register('jquery', $);
    Cube.register('lodash', _);
    
    • 注意 Cube.use 传入的参数寻址,基于当前 init的时候指定的base, 即跟目录下
    Cube.use('/app.js', cb);
    Cube.use('./app.js', cb);
    Cube.use('app.js', cb);
    

    以上是等效的,都引用了主类目下的 app.js 模块

    • cube支持remote源的模式
    Cube.init({
      remoteBase:{
        test: 'http://test.com/assets'
      }
    });
    

    当test.com的assets发布的时候设置了cube build --remote=test, 模块都会被设置一个remote命名空间,这样的remoteBase只要命名空间不冲突,可以实现站点间模块共享。

    服务器端API

    服务器端cube提供两种模式: 1. middleware模式, 2. 独立初始化 3. 命令行工具

    • middlware 模式
    const Cube = require('node-cube');
    let cube = Cube.middleware(options);
    
    • 独立初始化
    const Cube = require('node-cube');
    let cube = new Cube(options);
    

    配置对象 options

    {
      /**
       * 静态资源的绝对路径, 工程前端代码的根目录
       * @type {String}
       */
      root: ''
      /**
       * 端口
       * @type {Number}
       */
      port: 8080,
      /**
       * 是否middleware模式
       * @type {Boolean}
       */
      middleware: true,
      /**
       * 所有资源文件(如css中图片)的http前缀路径,
       * 一般是一个站点的绝对路径`/`,或者`http://`完整路径
       * @type {String}
       */
      base: '/',
      /**
       * 编辑模式下,缓存目录,默认在 $root/.cubecache
       */
      cacheDir: '',
      /**
       * 浏览器端文件缓存时间,最终会应用到http头:Cache-Control: public, maxAge=xxx
       * @type {Number}
       */
      maxAge: 600
      /**
       * 配置文件的处理器 processors
       * 这个配置更推荐在 package.json的 cube 属性中配置,这样build和debug的时候同时生效
       * @type {Object}
       */
      processors: {
        '.jsx': [
          ['cube-react', {}],  // processor with config
          'minify'
        ],                     // multi-processor
        '.jsw': 'jsw'          // single processor
      },
      /**
       * 开发模式下是否开启缓存, 默认开启
       * @type {Boolean}
       */
      devCache: true,
    
      /**
       * optimize file load on dev mode, default is true
       * @type {Boolean}
       * 开启加上之后,dev模式下会
       */
      optimize: true,
      /**
       * 模块映射, 主要是加速加载用, 大部分的模块其实已经有构建好的 ./dest/$mod.js
       * {
       *    react: './dest/react.min.js'
       * }
       */
      moduleMap: {}
      /**
       * 忽略依赖解析,主要是配合前端的 Cube.register()用
       * 在前端页面已经加载的公共资源,可以通过设置服务端的这个ignore来实现共享
       */
      ignoreModule: {
        react: true
      }
    }
    
    • cli模式
    # 本地开发的时候启动服务,指定静态文件目录,即可服务起来
    > cube start your_project_dir
    
    # 初始化工程, 初始化一个简单的case
    > cube init dir
    
    # 打包发布工程
    > cube build dir

    配置优先级

    构造函数传入 > package.json > cube内置配置

    • processors 优先级

      构造函数传入 > package.json中配置 > cube默认配置

    • ignoreRule 优先级

      ignoreRule的配置同等优先级,merge之后都会生效

      构造函数 = .cubeignore = package.json

    Customize Cube Processors

    一个典型的插件代码:

    var path = require('path');
    /**
     * 构造函数
     * @param {Cube} cube Cube instance
     */
    function CustomProcessor(cube) {
    	this.cube = cube;
    }
    CustomProcessor.type = 'style';
    CustomProcessor.ext = ['.sass'];
    CustomProcessor.prototype.process = function (data, options, callback) {
    	/**
       * 在这个函数中处理data对象,data.code已经拿到了源文件,例如less的处理
       * 就是将data.code编译成css,然后重新赋值回data.code。
       *  data {Object} 
       *    queryPath
       *    realPath
       *    code
       *    source
       */
    	callback(null, data);
    };
    module.exports = CustomProcessor;
    
    

    可参考目前已有的processor源码,来更快的理解自定义processor。

    Keywords

    none

    Install

    npm i node-cube

    DownloadsWeekly Downloads

    27

    Version

    3.2.0

    License

    MIT

    Unpacked Size

    379 kB

    Total Files

    53

    Last publish

    Collaborators

    • fishbar
    • fish
    • ericdum
    • albin3
    • elvira
    • hqidea