前后端分离之路 - Vue2项目多入口模板改造方案
<p>做前后端分离也有一段时间了,业务一直在用Vue@1.x的多入口方案,也一直懒癌发作没搞2.x的版本。适逢最近在等某宝小程序的构建,由于迟迟不定技术方案,只好暂缓先捯饬一下Vue@2.x项目多入口的构建方案。</p> <h2>关于项目模板</h2> <p>项目模板没有选择重新开发,而是直接选用了vue官方模板 vuejs-templates/webpack 。熟悉的开发者应该都了解,这是一个SPA模板,只有一个入口,而现在我们需要把它改成多入口,并且修改添加一些开发功能,以配合Koa-grace时的开发流程。</p> <p>可用的改造方案已经发布,有兴趣的同学可以 <strong>先体验基于Koa-grace的多入口项目方案</strong> :</p> <p><strong>Grace-vue-webpack-boilerplate --- </strong> 基于Koa-grace的多入口Vue@2.x项目构建方案 :rocket:</p> <p>关于官方模板,就不再分享学习的过程,下面仅讨论改造过程中 <strong>遇到的问题</strong> 和 <strong>实施方案的理由</strong> 。</p> <h2>关于目录结构</h2> <p>由于模板是为了基于Koa-grace的项目而设计,所以在目录结构上需保持基本的 Koa-grace项目结构 。</p> <p>以下列举了项目中关键文件夹及文件的结构关系,仅供参考。</p> <pre> <code class="language-javascript">. ├── package.json // 项目依赖 ├── node_modules │ ├── mock // mock数据文件 ├── controller // node层路由目录 │ ├── defaultCtrl.js │ └── home.js │ ├── views // 静态模板源码目录 ├── static // 静态资源源码目录 │ ├── image │ ├── fonts │ ├── css │ └── js │ ├── build // 编译脚本目录,本次重点改造 │ └── config // 项目配置,供编译过程 └── vues // 源码目录,下属文件夹将视作独立的页面入口,‘_’开头的文件夹将被忽略 ├── _components // 组件库,‘_’开头时将不会被作为入口 ├── demo // /demo页入口 └── home // /home页入口 ├── index.js ├── index.vue └── router.js</code></pre> <h2>关于多入口(Multiple Entry)</h2> <p>调整完文件结构,下面要解决的事情就是,在原有模板的基础上改造多入口方案。</p> <p>其实这一步很简单,只需拓展webpack配置文件中entry的获取方式即可:</p> <pre> <code class="language-javascript">// build/webpack.base.conf.js /** * [entries 入口合成器] * @param {object} opt 指定的入口,优先级高于自动抓取入口 * @return {object} 返回合成的入口对象 */ function entries (opt) { var ens = exec('cd ./vues && ls').split('\n').map(function(item) { var obj = {} // 将忽略所有以下划线“_”开头的文件夹 if (!/^_[\w-]+$/.test(item)) { obj[item] = './vues/'+item+'/' } return obj }) return Object.assign.apply(null, [].concat(ens, opt)) } module.exports = { entry: entries({ // 此处可以手动指定其他需打包的页面/文件入口 common: [ './static/css/common/reset.less', './static/css/common/index.less', './static/js/common/hello.js', ] }), ... }</code></pre> <p>以上代码效果相当于:</p> <pre> <code class="language-javascript">module.exports = { entry: { home: './vues/home/index.js', demo: './vues/demo/index.js', common: [ './static/css/common/reset.less', './static/css/common/index.less', './static/js/common/hello.js', ] }, ... }</code></pre> <p>对于多入口项目, 避免了手工更新入口的麻烦,在源码目录中创建入口文件夹并添加源码文件 即可。</p> <p>以上就完成了入口的改造,但这样还无法将文件按需要的目录结构产出,所以还需要调整产出配置。</p> <h2>关于文件产出(Files Output)</h2> <h3>产出规则及需求</h3> <p>按照项目结构,整理文件产出的需求:</p> <ul> <li>js <ul> <li>文件:编译后文件名应为build.js</li> <li>路径:需输出到static/js下,并存放于入口名称的文件夹内,如:static/js/home/build.js</li> </ul> </li> <li>css <ul> <li>文件:规则同上,如:build.css</li> <li>路径:规则同上,如:static/css/home/build.css</li> </ul> </li> <li>html <ul> <li>文件:产出文件名应为inde.html</li> <li>路径:需输出到views/下,如:views/home/index.html</li> </ul> </li> </ul> <p>改造时直接进行了webpack.prod.conf的全功能配置,webpack.dev.conf进行简化即可(开发阶段无需分离css、压缩代码、生成map、抽取公共依赖等步骤)。</p> <p>通过查看原项目模板的编译流程可以了解:</p> <ul> <li>js:作为entry配置,output直接影响输出路径及文件名</li> <li>css:entry中配置的部分同上,由vue文件中抽离的部分则需要插件 ExtractTextPlugin 抽离</li> <li>html:需要插件 HtmlWebpackPlugin 配合入口进行产出,可以使用ejs模板</li> </ul> <h3>产出html入口文件</h3> <p>首先,在webpack文档中可以了解到chunk的概念,它和entry是一一对应的,在多入口项目中尤为重要。</p> <p>Passing an array of file paths to the entry property creates what is known as a "multi-main entry". This is useful when you would like to <strong>inject multiple dependent files together</strong> and graph their dependencies <strong>into one "chunk"</strong> . --- webpack.js.org/entry-points</p> <p>其次,需要先产出可用的HTML文件,才能调试其他静态资源的加载。由于多入口化,HTML在产出时需要按chunk进行输出,才能保证对应入口的编译文件引用到对应的HTML中。因此需要按entry初始化对应的HtmlWebpackPlugin:</p> <pre> <code class="language-javascript">// build/webpack.prod.conf.js var webpackConfig = merge(utils.setEntrys(baseWebpackConfig), { ... } // // build/util.js function setEntrys (conf) { ... var htmlConfig = { // 压缩HTML选项,dev时不压缩 minify: { removeComments: isNotDev, collapseWhitespace: isNotDev, removeAttributeQuotes: isNotDev } } var entries = Object.keys(conf.entry) entries.map(function(ent) { ... // 根据entry添加新插件到plugins中 conf.plugins.push(new HtmlWebpackPlugin(Object.assign({ // HTML输出地址,形如:/Users/thunf/fe/server/app/demo/views/home/index.html filename: `${path.resolve(config.base.outputRoot, 'views')}/${ent}/index.html`, // 允许引用的chunk,包含本身及公共部分 chunks: [ent, 'vendor', 'manifest', 'common'], // 模板路径,形如:/Users/thunf/fe/server/app/demo/views/_common/_template.ejs template: path.resolve(projectRoot, 'views/_common/_template.ejs'), // 自动插入静态资源,由于结合使用了Koa-grace在Node预渲染HTML的功能,所以关闭该功能 inject: false, // Chunks排序规则 chunksSortMode: 'dependency' }, htmlConfig))) }); return conf; }</code></pre> <p>现在,我们可以通过Koa-grace提供的服务来打开对应的页面了,但是页面中的静态资源链接还存在问题。</p> <h3>产出js/css静态资源</h3> <p>此时需要配置输出的参数 output ,参考webpack文档( webpack.js.org/output | webpack-china.org/output ),可以查看output的说明和配置,其中本次需要使用的参数及有效说明如下:</p> <p><a href="/misc/goto?guid=4959738422897201348" rel="nofollow,noindex">output.filename</a> : This option <strong>determines the name</strong> of each output bundle.</p> <p><a href="/misc/goto?guid=4959738422994930041" rel="nofollow,noindex">output.path</a> : The output directory as an <strong>absolute</strong> path.</p> <p><a href="/misc/goto?guid=4959738423083300477" rel="nofollow,noindex">output.publicPath</a> : This option specifies the <strong>public URL</strong> of the output directory when referenced in a browser.</p> <p>简单来说,就是:</p> <ul> <li>output.filename:决定产出文件的名称和后缀</li> <li>output.path:影响文件输出的绝对位置(本机输出文件夹的绝对路径)</li> <li>output.publicPath:决定资源在浏览器中加载的路径(比如添加CDN、指定公开URL)</li> </ul> <p>假设我们需要在home页产出的html中生成 /demo/static/js/home/build.js?v=12345 的资源链接,对应以上规则有:</p> <ul> <li>output.filename: <strong> static/js/home/build.js?v=12345 </strong></li> <li>output.path: /Users/thunf/fe/server/app/demo <ul> <li>此路径为本地产出目录 <strong>绝对地址</strong> ,只影响本地产出目录,不影响html中输出的链接</li> </ul> </li> <li>output.publicPath: <strong> /demo/ </strong> <ul> <li>在html输出时,会直接 <strong>添加到filename前</strong> ,生成完整链接</li> <li><strong>将影响其他所有在html中引用的资源链接</strong></li> </ul> </li> </ul> <p>于是output应按以上规则配置,实际代码中 <strong>复用了路径配置及拼合路径的方法</strong> ,此处就不再进行代码分析。</p> <h3>文件加戳:Query or fileName</h3> <p>关于文件加戳的问题,为什么我们选择了 build.js?v=12345 ,而不是 build.12345.js ,是出于以下考虑的:</p> <p>1、每次改动build都会产出新文件,长久以往会导致线上代码版本过多</p> <p>2、上线仓储将越来越大,并且不易清理</p> <p>但实际应用上,Query戳对比fileName戳也有问题存在,比如</p> <p>1、无法有效利用CDN组合加速文件</p> <p>2、无法存在多版本</p> <p>但目前阶段根据业务需求,暂时足够使用,若有需要更改加戳方式的需求,只需在上述 output.filename 处将文件命名方式进行调整即可,此处不再累述。</p> <h3>其他资源路径问题</h3> <p>项目模板中目前还有图片资源及字体资源未提及,该两种资源在原模板中已存在loader及引用方式,下面描述碰到的问题及解决方法:</p> <p>生成图片引用路径</p> <p>由于在处理图片资源时,并没有很好的理解 output.publicPath 的作用,没有使用形如 /demo/ 的 <strong>相对于服务模式(server-relative)</strong> ,导致始终无法产出期望的文件路径。后来在webpack文档中找到具体的说明,才完成配置。</p> <p>The value of the option is prefixed to every URL created by the runtime or loaders. Because of this <strong>the value of this option ends with /</strong> in most cases. --- output.publicPath</p> <p>图片资源引用方式</p> <p>正常情况下,在.vue文件中可以使用相对路径来引用图片资源,但通过 <strong>配置别名</strong> 及 ~alias 的引用方式将 <strong>更简洁</strong> :</p> <pre> <code class="language-javascript"><!-- Same effect, but alias write less --> <img class="logo" src="../../static/image/logo-grace.png"> <img class="logo" src="~image/logo.png"></code></pre> <p>配置别名alias如下:</p> <pre> <code class="language-javascript">// build/webpack.base.conf.js module.exports = { ... resolve: { ... alias: { 'static': resolve('static'), 'image': resolve('static/image'), 'components': resolve('vues/_components') } }, ... }</code></pre> <p>.vue文件中其他静态资源引用同理</p> <pre> <code class="language-javascript"><!-- JS/Component --> <script> import Grace from 'components/grace.vue' </script> ... <!-- CSS/LESS --> <style lang="less"> @import '~static/fonts/iconfont.less'; </style></code></pre> <h2>关于提升开发效率</h2> <p>考虑实际开发中,有需要进行诸如本地配置、打开浏览器、创建新文件等重复性操作的场景。</p> <p>为了进一步</p> <p>懒癌发作 <strong>提升开发效率</strong></p> <p>,特别增加了一些增强功能,目前刚开始进行,欢迎抛出宝贵的建议。</p> <h3>自动配置开发环境</h3> <p>由于Koa-grace作为前后端分离框架,允许 <strong>同时解析多域名请求到多项目</strong> ,故以往在切换项目开发时,需要手动更改server.json配置及重启服务(官方吐槽:好烦啊喂)。那么既然项目启动需要单独 npm run dev 一次,为何不考虑将项目配置(开发环境)交由项目本身进行呢?</p> <pre> <code class="language-javascript">// build/check-server.js // 匹配grace下配置目录 function matchServerJson(graceRoot) { return glob.sync(path.join(graceRoot, '*/config/main.development.js')) || [] } ... // 匹配grace目录 function findServerFolder(graceRoot, scb, ecb) { var confMatch = matchServerJson(graceRoot) ;(1 === confMatch.length) ? callback(scb)({ serverRoot: path.resolve(confMatch[0], '../..'), serverConf: confMatch[0] }) : callback(ecb)(confMatch.length) }</code></pre> <p>于是本着尽可能</p> <p>懒癌发作 <strong>让系统自己找</strong></p> <p>的思想,通过引入glob进行关键文件的路径匹配,来验证当前项目是否符合Koa-grace目录规范,顺便解析出当前Koa-grace启动的文件夹(default: server)名称,并添加到config。</p> <p>有了server的路径,就可以按路径读取配置文件信息了,顺便也可以验证并添加本项目的配置:</p> <pre> <code class="language-javascript">// build/open-browser.js function lookForHost(hosts, autoOpenBrowser) { return Object.keys(hosts).filter(function(key, value) { // if vhost-matched, use the match one return hosts[key] === config.base.moduleName })[0] || (autoOpenBrowser && writeHostConf({ // if auto-open & no-vhost-matched, auto set "127.0.0.1": config.base.moduleName }) || [ // if no-auto-open & no-vhost-matched, to tip '> Maybe you have not set vhost to this app: ' + chalk.cyan(config.base.moduleName), '> Please set ' + chalk.magenta('vhost') + ' in ' + chalk.magenta('/server/config/server.json') + ' like this:', ' ' + chalk.green( JSON.stringify({ merge: {vhost: {"127.0.0.1": config.base.moduleName } } }, null, 2).replace(/\n/g, '\n ') ), '', '' ]) }</code></pre> <p>此处代码实现风格比较诡异,其实做了3种情况的判断:</p> <ul> <li>如果匹配到本项目的vhost配置,那就使用该host</li> <li>如果未匹配到,且允许自动打开浏览器,就 <strong> 写入默认配置 {127.0.0.1: moduleName} </strong></li> <li>如果未匹配到,且不允许自动打开浏览器,就发起提示</li> </ul> <h3>自动打开项目首页</h3> <p>其实这个功能在原项目模板中已经存在,只不过原项目自带server并且只有一个入口,启动时只需打开固定的首页即可。</p> <p>当变成多入口项目后,就需要面临新的问题:</p> <ul> <li>Koa-grace启动的host及端口不确定</li> <li>首页路径不确定</li> </ul> <p>第一个问题,通过上述方案已经可以解决。</p> <p>第二个问题,暂时需在config配置 autoOpenPage ,需在配置文件中添加如下配置,特此说明。</p> <pre> <code class="language-javascript">// build/config/index.js devConf = { ... autoOpenBrowser: true, // 是否自动打开浏览器 autoOpenDelay: 2000, // 延迟多少ms打开浏览器,koa-grace服务检测到路由文件变化会自动重启 autoOpenPage: 'home', // 自动打开时的项目入口(路由) ... };</code></pre> <h2>关于ESLint</h2> <h3>检查你的代码</h3> <p>Code linting is a type of static analysis.</p> <p>ESLint is designed to have all rules completely pluggable. --- eslint.org</p> <p>很早之前就了解过这个玩意了,曾经组里也有几次技术调研涉及这个,一直没正式投入使用过,也就自己搞一搞。</p> <p>其实开始使用时也是挺蛋疼的(模板自带配置使用标准: feross/standard ,感觉要求超级严格,比如“ { ”后换行并留一行空格都要error),但耐心看一下提示,就能知道格式哪里不标准,然后逐步就习惯了(避免写的时候太飘逸)。</p> <p>This module helps hold our code to a high standard of quality.</p> <p>This module ensures that new contributors follow some basic style standards. --- feross/standard</p> <p>这里吐个槽, 如果团队协作开发一个仓储,图快而不加以规范,简直就是给维护者挖坑 (版本越老坑越大,自己深有体会,靠嘴遁要求统一风格,真心没用,什么诡异的代码风格都有)。</p> <h3>翻一翻文档</h3> <p>某:eslint限制太严格</p> <p>我:嗯,确实严格,习惯就好</p> <p>某:能不能改成只有提示,但是不影响编译流程的</p> <p>我:看看文档</p> <ul> <li>eslint-loader: <a href="/misc/goto?guid=4959738423172353991" rel="nofollow,noindex">github.com/MoOx/eslint-loader</a></li> <li>eslint: <ul> <li>en: <a href="/misc/goto?guid=4959650077301376092" rel="nofollow,noindex">eslint.org/docs</a></li> <li>zh: <a href="/misc/goto?guid=4959738423298756208" rel="nofollow,noindex">eslint.cn/docs</a></li> </ul> </li> </ul> <p>研究了一下俩文档,理论上可以有2个方案实现 <strong>只提示而不影响编译流程</strong> ,但是似乎又各自有问题,以下是这两种方案。</p> <p>配置extends/rules</p> <p>在ESlint的官方文档里可以了解到 configuring#extending-configuration-files :</p> <ul> <li><strong>extends</strong> : <ul> <li>a string that specifies a configuration</li> <li>an array of strings: each additional configuration extends the preceding configurations</li> </ul> </li> <li><strong>rules</strong> : which rules are enabled and at what error level <ul> <li>enable additional rules</li> <li>change an inherited rule’s severity without changing its options</li> <li>override options for rules from base configurations</li> </ul> </li> </ul> <p>接下来通过查看 feross/standard 的配置文件 eslint-config-standard/eslintrc.json 可以得知,这个标准一言不合就error,而且 <strong>全部都是error</strong> (没办法,就是这么任性)。不过 feross/standard 的作者也这么表态了:</p> <p>The word "standard" has more meanings than just "web standard" :-)</p> <p>--- FAQ: But this isn't a real web standard!</p> <p>那么方案也就显而易见:</p> <ul> <li>找一份完全符合心意的标准(看起来比较难)</li> <li>写个插件,然后 <strong>自己定义规则</strong> ( eslint.org/docs/rules | eslint.cn/docs/rules ),添加到extends <ul> <li>比如强制缩进就给error,不关心是否空行就给warning,随心所欲so easy</li> </ul> </li> <li>在.eslintrc中,通过 <strong>添加rules属性,强行覆盖</strong> 现有extends提供的rules</li> </ul> <p>优缺点也一目了然:</p> <ul> <li>优:配置化并完全可以自定义,完全可拔插,可持续维护;</li> <li>缺:想找到一个完全符合心意的标准几乎不可能(若自己写规则,一般人怕是没这心情,虽然规则不是很多,哈)</li> </ul> <p>配置failOnWarning</p> <p>当然先讲一句,我其实 <strong>不推荐</strong> 这种配置,原因在后面说。</p> <p>首先在eslint-loader文档里,找到这么一句话:</p> <p>So even ESLint warnings will fail the build. --- eslint-loader#noerrorsplugin</p> <p>即使是warning也会阻断build过程。但有趣的是,option配置可以改变提示行为,默认值都是false:</p> <p>emitError: Loader will always return errors if this option is set to true.</p> <p>emitWarning: Loader will always return warnings if option is set to true.</p> <p>failOnWarning: Loader will cause the module build to fail if there are any eslint warnings.</p> <p>failOnError: Loader will cause the module build to fail if there are any eslint errors.</p> <p>以我的理解,eslint-loader应该是在preLoad阶段,以报错的形式影响webpack编译进程,并显示提示信息。</p> <p>所以在 eslint-loader的源码 里,找到了这么个地方:</p> <pre> <code class="language-javascript">// default behavior: emit error only if we have errors var emitter = res.errorCount ? webpack.emitError : webpack.emitWarning // force emitError or emitWarning if user want this if (config.emitError) { emitter = webpack.emitError } else if (config.emitWarning) { emitter = webpack.emitWarning } if (emitter) { emitter(messages) if (config.failOnError && res.errorCount) { throw new Error("Module failed because of a eslint error.\n" + messages) } else if (config.failOnWarning && res.warningCount) { throw new Error("Module failed because of a eslint warning.\n" + messages) } }</code></pre> <p>这段代码表明,正常流程上的warning和error是调用webpack自带的方法来emit的,只不过我们可以通过配置:</p> <p>1.emitError/emitWarning:取消default behavior,使emitter强制变成error/warning类型</p> <p>2.failOnWarning/failOnError:抛出一个Error来打断webpack的build过程</p> <p>那么问题来了,默认的配置 {emitError: false, failOnError: false} ,只是由webpack进行了一次emitError,并没有实际抛出一个Error,那实际上应该 <strong>不会 cause the module build to fail</strong> 才对?但实际开发时,比如为什么“ { ”后换行并留一行空格,不只触发了规则 no-trailing-spaces 的error,还导致webpack没有实际build出新文件呢?</p> <p>那么基本上可以断定这和webpack.emitError有关系了,来看一下webpack的源码:</p> <pre> <code class="language-javascript">// webpack/lib/NormalModule.js ... emitWarning: function(warning) { module.warnings.push(new ModuleWarning(module, warning)); }, emitError: function(error) { module.errors.push(new ModuleError(module, error)); }, ...</code></pre> <p>这里API功能是收集error和warning,那么理论上还有地方,会根据error和warning数量决定是否可以继续编译。</p> <p>中间调试的过程就不累述,最终在webpack的Compiler.js中先找到了判定emit并return的地方:</p> <pre> <code class="language-javascript">// webpack/lib/Compiler.js ... if(self.compiler.applyPluginsBailResult("should-emit", compilation) === false) { return self._done(null, compilation); } ...</code></pre> <p>经过寻找 should-emit 在哪里触发,然后找到在NoEmitOnErrorsPlugin中,处理errors数量的逻辑:</p> <pre> <code class="language-javascript">// webpack/lib/NoEmitOnErrorsPlugin.js ... compiler.plugin("should-emit", (compilation) => { if(compilation.errors.length > 0) return false; }); ...</code></pre> <p>此处可以看出,若errors中存在error,NoEmitOnErrorsPlugin会返回false,而对warning没有处理。这一行为会导致Compiler.js中的compile流程被中断,当然就不会有文件产出啦。</p> <p>那么为了验证这个逻辑,将NoEmitOnErrorsPlugin从项目build/webpack.dev.conf.js中注释掉之后,带着已知的格式问题(如多个空行,不影响实际编译),仍然可以编译出新文件,有兴趣的小伙伴可以自行尝试。当然这个插件在dev环境开发时还会影响其他loader的表现,不建议砍掉它。</p> <p>那么回到我们的问题上来,通过强制eslint触发emitWarning而不是emitError,即在eslint的option中配置 {emitWarning: true} , <strong>格式检测规则(编译无关的规则)</strong> 就不会终止webpack编译产出文件了:</p> <pre> <code class="language-javascript">... { test: /\.(js|vue)$/, loader: 'eslint-loader', ... options: { ... /* ======= begin ====== */ emitWarning: true /* ======= end ====== */ } }, ...</code></pre> <p>当然如果是会引起编译的错误,在接下来的编译中该断还是得断,还有可能产生多次log(毕竟没有被eslint在preLoad过程中拦下来,eslint提示完,后面的loader还会继续提示,比如重复显示error,调试过程简直最强大脑有木有)</p> <p>所以尽管可以实现 <strong>只提示而不影响编译流程</strong> 的目标,但又带来了新问题,虽然简单快捷但并不优雅,也没有让eslint发挥出什么作用(对非强迫症患者,仅提示还是拦不住的各种诡异风格的)。</p> <p>这就是不推荐的理由。总之blabla这么多,就是想说下面这句话。</p> <h3>不想用就别硬用</h3> <p>实在不能接受,那就干掉吧,推荐下面的方式。</p> <ul> <li>1、 Fork It And Make Your Own</li> <li>2、Comment out or delete the codes below (the part between comments): <pre> <code class="language-javascript">// build/webpack.base.conf.js ... module: { rules: [ /* ==================== eslint =================== */ /* If eslint makes you mad, just delete these code */ { test: /\.(js|vue)$/, loader: 'eslint-loader', enforce: "pre", include: [resolve('vues'), resolve('test')], options: { formatter: require('eslint-friendly-formatter') } }, /* ================== eslint end ================= */ ... ] ... } ...</code></pre> </li> <li>3、Enjoy your code : )</li> </ul> <h2>其他问题</h2> <h3>报错信息不显示</h3> <p>有小伙伴反应这一现象,如下图所示。其实这跟个人使用的terminal配色方案有关(webpack显示错误代码的颜色,正好跟terminal的背景色相同,就看不到了嘛),。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/849f4a9aba792722855947fbd5dcd136.png"></p> <p>经过调试,发现这种提示是由 eslint-friendly-formatter 打印出来的,根据源码显示:</p> <pre> <code class="language-javascript">... var parseBoolEnvVar = function(varName) { var env = process.env || { }; return env[varName] === 'true'; }; var subtleLog = function(args) { return parseBoolEnvVar('EFF_NO_GRAY') ? args : chalk.gray(args); }; ...</code></pre> <p>avoidTerminalColorGray</p> <p>只需配置 process.env.EFF_NO_GRAY = true 即可阻止使用chalk.gray显示文字。</p> <p>那么这个配置也将 <strong>加入项目的配置文件,如下配置</strong> 即可</p> <pre> <code class="language-javascript">// build/config/index.js ... devConf = { ... avoidTerminalColorGray: true }; ...</code></pre> <h2>NEXT</h2> <h3>抽取代码(TODO)</h3> <p>有时间将抽离 <strong>提升开发效率</strong> 部分的逻辑为插件,以帮助更多其他技术栈的Koa-grace项目更好的提升开发体验。</p> <h3>自动创建新入口(TODO)</h3> <p>已经有同学提出需要自动创建新入口的脚本及命令,这个近期也会提供(每次添加新入口要创建好几个文件夹及文件也是麻烦)</p> <h3>热加载(TODO)</h3> <p>该功能在原模板中存在,但升级多入口后,server将由Koa-grace接管,目前已移除该部分代码,下一步考虑添加Koa-grace的中间件,来配合完成vue项目的热加载方案</p> <h3> </h3> <p> </p> <p>来自:http://feclub.cn/post/content/grace-vue-boilerplate</p> <p> </p>
本文由用户 yushenhw 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!