进阶使用

获取 YKit 内部 Webapck 实例

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

  1. module.exports = {
  2. plugins: ['qunar'],
  3. config: {
  4. exports: ['./scripts/app.js'],
  5. modifyWebpackConfig: function(baseConfig) {
  6. baseConfig.plugins = baseConfig.plugins.concat([
  7. // 通过 this.webpack 可获取到 webpack 实例
  8. new this.webpack.optimize.DedupePlugin()
  9. ])
  10. return baseConfig;
  11. }
  12. }
  13. };

获取当前环境变量

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

  • local - 本地环境配置,在 ykit server 中访问项目会生效
  • dev - 开发环境配置,在 ykit pack 时生效
  • prd - 生产环境配置,在 ykit pack -m 时生效
  1. module.exports = {
  2. plugins: ['qunar'],
  3. config: {
  4. exports: ['./scripts/app.js'],
  5. modifyWebpackConfig: function(baseConfig) {
  6. // 示例 - 根据当前环境设置环境变量
  7. var ENV_PARAMS = {};
  8. switch (this.env) {
  9. case 'local':
  10. ENV_PARAMS = {name: 'a'};
  11. break;
  12. case 'dev':
  13. ENV_PARAMS = {name: 'b'};
  14. break;
  15. case 'prd':
  16. ENV_PARAMS = {name: 'c'};
  17. break;
  18. default:
  19. }
  20. baseConfig.plugins.push(new this.webpack.DefinePlugin({
  21. ENV_PARAMS: JSON.stringify(ENV_PARAMS)
  22. }))
  23. // 之后在代码中使用时直接调用变量即可,如在 app.js 中:
  24. // console.log(ENV_PARAMS.name)
  25. return baseConfig;
  26. }
  27. }
  28. };

提取公共模块

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

  1. module.exports = {
  2. config: {
  3. // 基于当前源代码目录,默认为 "src"
  4. exports: [
  5. './scripts/a.js',
  6. './styles/b.js'
  7. ],
  8. commonsChunk: {
  9. name: 'common', //name是生成公共模块的chunkname, 会提取入口文件a.js和b.js公共模块
  10. minChunks: 2, //公共模块被使用的最小次数。比如配置为3,也就是同一个模块只有被3个以外的页面同时引用时才会被提取出来作为common chunks,默认为2
  11. vendors: { //vendors是一个处理第三方库的配置项,结构是一个key,value数组,key是chunkname,value是第三方类库数组
  12. lib: ['jquery', 'underscore', 'moment'],
  13. charts: ['highcharts', 'echarts']
  14. }
  15. }
  16. }
  17. };

配置 vendors 第三方公共类库,会多打出 manifest.js 文件,这是为了解决 webpack 不管修改哪个文件都导致 hash 改变的问题。你需要单独在 html 中添加一个 script 标签来引用它。如 ``,且要放置在其它 script 标签前面。

  • 示例1 - 提取 common 模块代码
  1. module.exports = {
  2. config: {
  3. exports: [
  4. './scripts/a.js',
  5. './scripts/b.js'
  6. ],
  7. commonsChunk: {
  8. name: 'common'
  9. }
  10. }
  11. }

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

  • 示例2 - 提取第三方公共类库代码
  1. module.exports = {
  2. config: {
  3. exports: [
  4. './scripts/a.js',
  5. './scripts/b.js'
  6. ],
  7. commonsChunk: {
  8. vendors: {
  9. lib: ['react-dom', 'react'],
  10. charts: ['highcharts', 'echarts']
  11. }
  12. }
  13. }
  14. }

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

  • 示例3 - 提取 common 模块代码 和 提取第三方公共类库代码
  1. module.exports = {
  2. config: {
  3. exports: [
  4. './scripts/a.js',
  5. './scripts/b.js'
  6. ],
  7. commonsChunk: {
  8. name: 'common',
  9. vendors: {
  10. lib: ['react-dom', 'react'],
  11. charts: ['highcharts', 'echarts']
  12. }
  13. }
  14. }
  15. }

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

自定义中间件

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

使用 this.applyMiddleware 添加中间件:

  1. var path = require('path');
  2. module.exports = {
  3. plugins: ['qunar'],
  4. config: {
  5. exports: ['./scripts/app.js'],
  6. modifyWebpackConfig: function(baseConfig) {
  7. // 示例:处理 .hello 类型文件,全部返回文字 "hello!"
  8. this.applyMiddleware((req, res, next) => {
  9. if(path.extname(req.url) === '.hello') {
  10. res.end('hello!'); // 直接返回结果
  11. } else {
  12. next(); // 不进行处理,转给后续中间件
  13. }
  14. })
  15. return baseConfig;
  16. }
  17. }
  18. };

中间件作用域

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

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

错误处理

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

  1. this.applyMiddleware((req, res, next) => {
  2. try{
  3. // 自定义逻辑
  4. } catch(e) {
  5. console.log('middleware error: ', e);
  6. next();
  7. }
  8. })