进阶使用

获取 YKit 内部 Webapck 实例

modifyWebpackConfig 函数中从 this 可以获取到以下属性。

module.exports = {
    plugins: ['qunar'],
    config: {
        exports: ['./scripts/app.js'],
        modifyWebpackConfig: function(baseConfig) {
            baseConfig.plugins = baseConfig.plugins.concat([
                // 通过 this.webpack 可获取到 webpack 实例
                new this.webpack.optimize.DedupePlugin()
            ])
            return baseConfig;
        }
    }
};

获取当前环境变量

通过 this.env 可获取当前 YKit 的执行环境,可用的环境有:

  • local - 本地环境配置,在 ykit server 中访问项目会生效
  • dev - 开发环境配置,在 ykit pack 时生效
  • prd - 生产环境配置,在 ykit pack -m 时生效
module.exports = {
    plugins: ['qunar'],
    config: {
        exports: ['./scripts/app.js'],
        modifyWebpackConfig: function(baseConfig) {
            // 示例 - 根据当前环境设置环境变量
            var ENV_PARAMS = {};
            switch (this.env) {
                case 'local':
                    ENV_PARAMS = {name: 'a'};
                    break;
                case 'dev':
                    ENV_PARAMS = {name: 'b'};
                    break;
                case 'prd':
                    ENV_PARAMS = {name: 'c'};
                    break;
                default:
            }

            baseConfig.plugins.push(new this.webpack.DefinePlugin({
                ENV_PARAMS: JSON.stringify(ENV_PARAMS)
            }))

            // 之后在代码中使用时直接调用变量即可,如在 app.js 中:
            // console.log(ENV_PARAMS.name)

            return baseConfig;
        }
    }
};

提取公共模块

通过 config.commonsChunk 配置项可提取公共模块(基于 CommonsChunkPlugin 插件封装):

module.exports = {
    config: {
        // 基于当前源代码目录,默认为 "src"
        exports: [
            './scripts/a.js',
            './styles/b.js'
        ],

        commonsChunk: {
            name: 'common',    //name是生成公共模块的chunkname, 会提取入口文件a.js和b.js公共模块
            minChunks: 2,      //公共模块被使用的最小次数。比如配置为3,也就是同一个模块只有被3个以外的页面同时引用时才会被提取出来作为common chunks,默认为2
            vendors: {    //vendors是一个处理第三方库的配置项,结构是一个key,value数组,key是chunkname,value是第三方类库数组
                lib: ['jquery', 'underscore', 'moment'],
                charts: ['highcharts', 'echarts']
            }
        }
    }
};
配置 vendors 第三方公共类库,会多打出 manifest.js 文件,这是为了解决 webpack 不管修改哪个文件都导致 hash 改变的问题。你需要单独在 html 中添加一个 script 标签来引用它。如 ``,且要放置在其它 script 标签前面。
  • 示例1 - 提取 common 模块代码
module.exports = {
    config: {
        exports: [
            './scripts/a.js',
            './scripts/b.js'
        ],
        commonsChunk: {
            name: 'common'
        }
    }
}

示例1这段代码会提取 a.js 和 b.js 公共模块到 commonChunk

  • 示例2 - 提取第三方公共类库代码
module.exports = {
    config: {
        exports: [
            './scripts/a.js',
            './scripts/b.js'
        ],
        commonsChunk: {
            vendors: {
                lib: ['react-dom', 'react'],
                charts: ['highcharts', 'echarts']
            }
        }
    }
}

示例2这段代码会提取 a.js 和 b.js 的第三方 react-dom , react 模块到 libChunk ,提取 highcharts 和 echarts 到 chartsChunk

  • 示例3 - 提取 common 模块代码 和 提取第三方公共类库代码
module.exports = {
    config: {
        exports: [
            './scripts/a.js',
            './scripts/b.js'
        ],
        commonsChunk: {
            name: 'common',
            vendors: {
                lib: ['react-dom', 'react'],
                charts: ['highcharts', 'echarts']
            }
        }
    }
}

示例3这段代码不仅会提取 a.js 和 b.js 公共模块到 commonChunk,还会提取 a.js 和 b.js 的第三方 react-dom, react 模块到 libChunk , highcharts 和 echarts 提取到 chartsChunk

自定义中间件

YKit server 是基于 connect 实现的,在启动本地服务后,YKit 允许开发者添加自定义 connect 中间件处理请求(什么是中间件?)。

使用 this.applyMiddleware 添加中间件:

var path = require('path');
module.exports = {
    plugins: ['qunar'],
    config: {
        exports: ['./scripts/app.js'],
        modifyWebpackConfig: function(baseConfig) {
            // 示例:处理 .hello 类型文件,全部返回文字 "hello!"
            this.applyMiddleware((req, res, next) => {
                if(path.extname(req.url) === '.hello') {
                    res.end('hello!'); // 直接返回结果
                } else {
                    next(); // 不进行处理,转给后续中间件
                }
            })
            return baseConfig;
        }
    }
};

中间件作用域

默认情况下,在项目中自定义的中间件只对项目内的请求生效。假如该项目叫 myapp,则中间件只对 http://localhost/myapp/* 下的请求生效。如果希望在 http://localhost/* 下生效可以添加 global 配置:

this.applyMiddleware((req, res, next) => {
    // 自定义逻辑
    next();
}, {global: true}) // 作用于全局

错误处理

在 connect 中间件中的错误并不会被抛出,这是为了防止意外终止 server 进程,如果希望报错可以手动进行 try catch:

this.applyMiddleware((req, res, next) => {
    try{
        // 自定义逻辑
    } catch(e) {
        console.log('middleware error: ', e);
        next();
    }
})