初探 Node.js 框架:eggjs (环境搭配篇)
<p><span style="color: rgba(0, 204, 255, 1); font-size: 2em">eggjs 是一个优秀的 Node.js 框架</span></p><p><strong>概述:为什么标题上说 eggjs 是一个优秀的 Node.js 框架(可跳过)?</strong></p>
<p>换言之,我们为什么选择 eggjs 进行开发而不是之前初学时使用的 Express 框架呢?</p>
<p> </p>
<p> <span style="color: rgba(136, 136, 136, 1)">Express 是最著名的 Node.js 框架,它甚至是官方唯一推荐过的(目前)</span></p>
<p><span style="color: rgba(136, 136, 136, 1)"> 但是根据实际开发,我觉得它的配置相当冗长,比方说:它可以一句 app.use() 布满长达数十行</span></p>
<p><span style="color: rgba(136, 136, 136, 1)"> 这一点,我没法继续使用下去,所以就停止对它的学习。</span></p>
<p> </p>
<p>就配置方面来说: eggjs 做得很好,它通过开发约束,将所有的配置文件放置在 config 文件中。</p>
<p>起初加载时便进行逐一对服务器进行设置,后设置的将会覆盖之前的。配置则是基于 类似 json 一样的写法,这使得我们容易定位某一处配置并进行修改(因为 key 不能重复,检索一下就知道在哪了)</p>
<p> </p>
<p>同样的,eggjs 拥有大量的插件,开发者需要怎样的功能,在官方插件上几乎都可以找到。</p>
<p>如果没有找到所需插件,eggjs 也支持定制。</p>
<p>在这里可以找到官方 API 以及使用文档:https://eggjs.org/zh-cn/</p>
<p> </p>
<p>不再进行多说了,让我们开始进行一个 eggjs 框架工程吧(跟官方的有些不同,按照官方的快速入门,总是遇到莫名其妙的错误)</p>
<p>官方的错误,配置让我耗费了三四个小时才得以真正明白框架的使用方法,希望你看完这篇文章,只需半小时就能写出一个高质量的项目</p>
<p> </p>
<h2><span style="color: rgba(0, 204, 255, 1)">1.1 使用 脚手架 进行初步的工程目录建立</span></h2>
<p>这一步也是所有基于 Node.js 工程所必备的环节之一:当然,你也可以手动创建。</p>
<p>打开 DOS / 终端 ,使用以下命令转到你需要存放的项目位置(这里是我的项目存放位置):</p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="font-size: 14px">cd C:\Users\chong\Documents\NodeJS</span></pre>
</div>
<p> </p>
<p>我是在 Windows 系统下的 “文档” 中创建了一个 NodeJS 目录,它将是我用于所有 Node 项目的根目录。</p>
<p>创建一个项目文件夹并进入( project 是项目名称,可更改):</p>
<div class="cnblogs_code">
<pre><span style="font-size: 14px"><span style="color: rgba(0, 0, 255, 1)">mkdir</span> project && cd project</span></pre>
</div>
<p> </p>
<p>在这里,开始进行 脚手架 的初始化和安装依赖并进行启动:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(51, 153, 102, 1); font-size: 14px"># 初始化目录(会创建必备的文件夹和JS,package.json 文件)<br>npm init egg --type=simple<br>
# 安装依赖
npm i<br></span></pre>
</div>
<p> </p>
<p>执行初始化目录的时候,需要你填写一些信息,这些信息最终都会导入 package.json 配置文件中。</p>
<p> </p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211203351594-527011848.png" alt=""></p>
<p> </p>
<p> </p>
<p> </p>
<p>红框是 eggjs 初始化时创建的文件以及文件夹,后续我们再来了解它们的作用<strong>【重要】</strong></p>
<p>而箭头所指的则是需要填写的信息,例如项目名称,描述信息,作者以及 Cookie 密钥</p>
<p> </p>
<p>现在,你已经得到了一个较为完整的目录结构(我已经运行过几次,比刚创建的还多了一些文件,不必在意):</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211203907134-483897624.png" alt=""></p>
<p> </p>
<p> </p>
<p>好了,再启动项目,这里有几种启动方式:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(51, 153, 102, 1); font-size: 14px"># 启动项目</span><br><span style="color: rgba(51, 153, 102, 1); font-size: 14px">npm run dev<br><br>npm start</span></pre>
</div>
<p> </p>
<p>npm start 属于生产环境中使用,使用这种方式的话,需要打印信息输出到控制台就看不到了。</p>
<p>而<span style="color: rgba(255, 0, 0, 1)"> npm run dev</span> 是开发中所推荐的启动方式,当你修改代码时,则不必手动重启服务器,eggjs 会自己重启,你只需要等待一会就可以在浏览器看到相对应的修改。</p>
<p>重要的是:你随时可以在代码中写上 console.log ,控制台也会有相应的显示。</p>
<p> </p>
<p>下方是多种启动或测试的命令( package.json ),均在前方加入 npm 即可使用。</p>
<p>也可以修改它们,如果你需要换个端口,例如 dev,修改为 <span style="color: rgba(255, 0, 0, 1)">egg-bin dev --port 8081</span> (注意:两个 <span style="color: rgba(255, 0, 0, 1)">-</span> 符号)</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211204424412-776029822.png" alt=""></p>
<p> </p>
<p> </p>
<p> </p>
<p>启动完成后,在浏览器中访问 DOS / 终端 显示的路径(红色箭头):</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211210053033-849527914.png" alt=""></p>
<p> </p>
<p> </p>
<p> </p>
<p>黄色部分是被修改的文件,在这里不必理会。</p>
<p>到这里,你的初始化工作已经做完,不妨休息会,再继续往下阅读。</p>
<p> </p>
<p> </p>
<h2><span style="color: rgba(0, 204, 255, 1)">1.2 了解各个目录、文件的作用以及 eggjs 如何处理它们</span></h2>
<p>相信你已经成功初始化了吧,现在让我们来了解 eggjs 的目录结构,各个文件的作用:</p>
<p>重新回到之前的一张图,我们可以清晰地看见 eggjs 到底创建了什么。</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211210609503-867345660.png" alt=""></p>
<p> </p>
<p> </p>
<p> </p>
<p>前一些以 . 开头的文件我们不必理会,从 package.json 文件开始(我们已经知道这是配置文件),往下看:</p>
<p>它创建了两个文件夹,分别是: app、config (test 属于测试,如单元测试等,我们也不必理会)</p>
<p> </p>
<p>app 是网站处理用户请求,以及浏览器请求服务器资源的应用文件夹</p>
<p>它包含:router(路由文件)、controller(处理器)</p>
<p>是的,初始化就这么两个,所以我建议在 app 目录下再手动创建以下几个文件夹:</p>
<p> </p>
<p>public(存放静态资源,如 css、js、img)</p>
<p>view (存放视图文件)</p>
<p>service(处理数据等业务操作)</p>
<p> </p>
<p>先来详细说说路由文件,所有的网站都会有一个访问地址,路由则是客户端首先进入位置:</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211211905536-1344196763.png" alt="" width="634" height="325"></p>
<p> </p>
<p> </p>
<p>客户端(浏览器)会发送一个请求,这个请求将会首先进入路由分发文件,匹配成功到某一个 处理器(Controller)后</p>
<p>这个处理器将会去进行相关业务操作(<span style="color: rgba(255, 0, 0, 1)">Service</span>)拿到数据,之后 <span style="color: rgba(255, 0, 0, 1)">view</span> 渲染一个页面成功后一层层返还回去。</p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)">controller</span> 文件夹下则放置着我们所有核心的网站代码(后续解释)</p>
<p> </p>
<p>任何一个网站都需要进行配置,而所有的 Web服务器 都应该自身有创建环境的能力,而不是人为去为这个服务器配置好环境。</p>
<p>那么 <span style="color: rgba(255, 0, 0, 1)">config</span> 文件夹就是为此而生。</p>
<p> </p>
<p>由前面得知:eggjs 有着丰富的插件,所以必然有一个插件的管理、配置文件,它就是 <span style="color: rgba(255, 0, 0, 1)">plugin.js </span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">后续我们将知道一个插件应该怎样启用,关闭,安装,这里先不说明;</span></span></p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">eggjs 最重要的配置文件则是 :<span style="color: rgba(255, 0, 0, 1)">config.default.js</span>,它管理着整个 Node服务器 的所有配置,包括插件、Cookie安全密钥、视图渲染等等配置。</span></span></p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">好了,看到这里你已经对生成的 eggjs 项目工程有了一个大致的了解(我昨天才接触 node.js ,若有不对,望在评论中指出,我会进行修改,多谢)</span></span></p>
<p> </p>
<h2><span style="color: rgba(0, 204, 255, 1)">1.3 了解一个请求是如何被处理的【重要】</span></h2>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">读完前面,你已经明白:eggjs 工程中的目录,文件的作用(只介绍了部分),现在让我们来深入了解代码层次上,eggjs 如何处理用户请求(不解析源码,从生成的文件来看):</span></span></p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">先来了解路由文件怎样工作(建议所有的路由设计都放在一个文件中):</span></span></p>
<div class="cnblogs_code">
<pre>'use strict'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* @param {Egg.Application} app - egg application
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
module.exports </span>= app =><span style="color: rgba(0, 0, 0, 1)"> {
const { router, controller } </span>=<span style="color: rgba(0, 0, 0, 1)"> app;
router.get(</span>'/'<span style="color: rgba(0, 0, 0, 1)">, controller.main.index);
};</span></pre>
</div>
<p> </p>
<p><span style="color: rgba(0, 204, 255, 1)">router.get() </span>方法指的是 GET 请求。</p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">第一个参数表示 URL,例如 www.cnblogs.com 是域名,那么 www.cnblogs.com/index 中的 / 开始,则都是该网站下的‘路由’</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">第二个参数表示 controller 文件夹下的 main.js 中的 index 方法<strong>【重要】</strong>,如下:</span></span></p>
<div class="cnblogs_code">
<pre>'use strict'<span style="color: rgba(0, 0, 0, 1)">;
<span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 204, 255, 1)">Controller</span> </span>= require('egg'<span style="color: rgba(0, 0, 0, 1)">).Controller;
<span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 204, 255, 1)">MainController</span> extends <span style="color: rgba(0, 204, 255, 1)">Controller</span> {
async index() {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.ctx.body = <span style="color: rgba(0, 128, 0, 1)">'<h1>Hello world</h1>'</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
module.exports </span>= <span style="color: rgba(0, 204, 255, 1)">MainController</span>;</pre>
</div>
<p> </p>
<p>所以,你会在浏览器的窗口中看见:</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211214939693-1450454829.png" alt=""></p>
<p> </p>
<p> </p>
<p>看,你已经知道它的请求过程了!先在 router.js 文件中找到用户请求的位置,而网站进入默认是 / </p>
<p>所以我们已经捕获到了这次请求,之后根据路由文件的描述找到 controller 文件夹下的 main 文件,在从中检索到 index 方法</p>
<p>这个方法设置了body,让它输出一个 h1 标签,写上 Hello world 。</p>
<p> </p>
<p><span style="font-size: 15px">即 <span style="color: rgba(0, 204, 255, 1)">router -> controller.main.index() </span></span></p>
<p> </p>
<p>但是这样的网站根本不具备使用能力,留不住用户,我们还需要根据不同用户数据,渲染一个好看的页面给用户。</p>
<p>这时,我们就可以知道 eggjs 插件的强大之处了(再缓缓,梳理下阅读到的知识,准备好了再继续了解吧)。</p>
<p> </p>
<p> </p>
<h2><span style="color: rgba(0, 204, 255, 1)">1.4 通过模板引擎渲染页面</span></h2>
<p>eggjs 强大的插件足以使你在 Node服务器 上做到与其它Web服务器不同的体验</p>
<p>先述说模板引擎,之后,让我们了解一下网站多语言一键配置。</p>
<p> </p>
<p><span style="font-size: 16px; color: rgba(0, 204, 255, 1)">以 Nunjucks 模板引擎为例:</span></p>
<p>首先引入两个插件:egg-view、egg-view-nunjucks</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 128, 0, 1); font-size: 15px">npm i egg-view -save
npm i egg-view-nunjucks -save</span></pre>
</div>
<p> </p>
<p>之后打开 config/config.default.js 文件:</p>
<div class="cnblogs_code">
<pre>'use strict'<span style="color: rgba(0, 0, 0, 1)">;
const path </span>= require('path'<span style="color: rgba(0, 0, 0, 1)">);
module.exports </span>= appInfo =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cookie 安全密钥</span>
keys: "_skfhj8546542354.16554"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 项目日志存放文件夹</span>
<span style="color: rgba(0, 0, 0, 1)"> logger: {
dir: path.join(appInfo.baseDir, </span>'logs'<span style="color: rgba(0, 0, 0, 1)">),
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 渲染模板配置</span>
<span style="color: rgba(0, 0, 0, 1)"> view: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 配置视图根路径</span>
root: path.join(appInfo.baseDir, 'app/view'<span style="color: rgba(0, 0, 0, 1)">),
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否缓存路径</span>
cache: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 配置文件默认扩展名</span>
defaultExtension: '.nj'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认渲染模板引擎</span>
defaultViewEngine: 'nunjucks'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 文件映射配置</span>
<span style="color: rgba(0, 0, 0, 1)"> mapping: {
</span>'.nj': 'nunjucks'<span style="color: rgba(0, 0, 0, 1)">
}
}</span><span style="color: rgba(0, 0, 0, 1)">
};
};</span></pre>
</div>
<p> </p>
<p>我已经注明了各个属性的作用,可复制到你的文件中。</p>
<p>之后启用插件:egg-view-nunjucks,打开 config/plugin.js 文件</p>
<div class="cnblogs_code">
<pre>'use strict'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 模板引擎:用于渲染页面数据
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
exports.nunjucks </span>=<span style="color: rgba(0, 0, 0, 1)"> {
enable: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
package: </span>'egg-view-nunjucks'<span style="color: rgba(0, 0, 0, 1)">,
};</span></pre>
</div>
<p> </p>
<p>配置方面已经准备完毕,之后需要在 app/view 目录下创建一个 index.nj 模板文件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>{{ page_title }}<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">></span>{{ page_content }}<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p>
<p>双括号是模板引擎的语法之一,还有循环等(是不是觉得跟 jsp 差不多)</p>
<p>好了,让我们修改 controller/main.js 文件</p>
<div class="cnblogs_code">
<pre>'use strict'<span style="color: rgba(0, 0, 0, 1)">;
const Controller </span>= require('egg'<span style="color: rgba(0, 0, 0, 1)">).Controller;
class MainController extends Controller {
async index() {
const { ctx } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
await ctx.render(</span>'index'<span style="color: rgba(0, 0, 0, 1)">,{
page_title : </span>"标题"<span style="color: rgba(0, 0, 0, 1)">,
page_content : </span>"模板引擎所渲染的页面"<span style="color: rgba(0, 0, 0, 1)">
});
}
}
module.exports </span>= MainController;</pre>
</div>
<p> </p>
<p>注意:请加上 await 关键字,它表示等待一个 Promise 对象,如果不加上,会出现 404 错误,</p>
<p>因为在渲染过程中,处理器却返回了结果(没数据的结果),自然客户端也会认为服务器没有找到资源。</p>
<p> </p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211222240553-1657416233.png" alt=""></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>现在已经跟我们所想的一致,那么到这里,你已经具备了开发一个项目的能力;</p>
<p>之后会逐步介绍数据库连接,数据处理等方法。敬请期待。</p>
<p> </p>
<p> </p>
<h3><span style="color: rgba(0, 204, 255, 1)">1.4.1 多语言配置(将会引用一些官方例子)</span></h3>
<p>多语言显示(按需配置),很简单,基于插件扩展能力,我们首先在 config.default.js 中增加配置,完整看起来是这个样子的:</p>
<div class="cnblogs_code">
<pre>'use strict'<span style="color: rgba(0, 0, 0, 1)">;
const path </span>= require('path'<span style="color: rgba(0, 0, 0, 1)">);
module.exports </span>= appInfo =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cookie 安全密钥</span>
keys: "_tourism_2650159865482545.265"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 项目日志存放文件夹</span>
<span style="color: rgba(0, 0, 0, 1)"> logger: {
dir: path.join(appInfo.baseDir, </span>'logs'<span style="color: rgba(0, 0, 0, 1)">),
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 渲染模板配置</span>
<span style="color: rgba(0, 0, 0, 1)"> view: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 配置视图根路径</span>
root: path.join(appInfo.baseDir, 'app/view'<span style="color: rgba(0, 0, 0, 1)">),
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否缓存路径</span>
cache: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 配置文件默认扩展名</span>
defaultExtension: '.qyml'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认渲染模板引擎</span>
defaultViewEngine: 'nunjucks'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 文件映射配置</span>
<span style="color: rgba(0, 0, 0, 1)"> mapping: {
</span>'.qyml': 'nunjucks'<span style="color: rgba(0, 0, 0, 1)">
}
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 多语言配置</span>
<span style="color: rgba(0, 0, 0, 1)"> i18n: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认语言,默认 "en_US"</span>
defaultLocale: 'zh-CN'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> URL 参数,默认 "locale"</span>
queryField: 'locale'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cookie 记录的 key, 默认:"locale"</span>
cookieField: 'locale'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cookie 的 domain 配置,默认为空,代表当前域名有效</span>
cookieDomain: ''<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cookie 默认 `1y` 一年后过期, 如果设置为 Number,则单位为 ms</span>
cookieMaxAge: '1y'<span style="color: rgba(0, 0, 0, 1)">,
}
};
};</span></pre>
</div>
<p> </p>
<p>第二步:将 egg-i18n 插件进行安装,并写入项目配置文件中</p>
<div class="cnblogs_code">
<pre>npm i egg-i18n -save</pre>
</div>
<p> </p>
<p>最新版的 eggjs 中默认开启多语言插件,所以我们不必手动启用。</p>
<p> </p>
<p>之后在 config 目录下创建一个 locale 文件夹<strong>【重要:拼写一定要正确】</strong></p>
<p>在 locale 文件夹中创建所需配置的语言文件(图仅示例两种),可以是 JSON 文件,也可以是 JS 文件,大概是这样的(我的是 JS 格式):</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211223311739-1361030448.png" alt=""></p>
<p> </p>
<p> </p>
<p>所有的多语言开发都会基于一种语言,我以英语为例(国际化也都是英语):</p>
<p>zh-CN.js 是这样配置的(用官方的例子):</p>
<div class="cnblogs_code">
<pre>module.exports = {
"Email": "邮箱",
"Welcome back, %s!": "欢迎回来,%s!"
};</pre>
</div>
<p> </p>
<p>如果你是基于 JSON 文件,也就是 zh-CN.json ,那么编写是这个样子的:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span>"Email": "邮箱"<span style="color: rgba(0, 0, 0, 1)">,
</span>"Welcome back, %s!": "欢迎回来,%s!"<span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p> </p>
<p>就算是英语也需要配置:</p>
<p>en_US.js 会是这样编写的:</p>
<div class="cnblogs_code">
<pre>module.exports =<span style="color: rgba(0, 0, 0, 1)"> {
</span>"Email": "Email"<span style="color: rgba(0, 0, 0, 1)">,
</span>"Welcome back, %s!": "Welcome back,%s!"<span style="color: rgba(0, 0, 0, 1)">
};</span></pre>
</div>
<p> </p>
<p>至于 %s %d 之类的 format 标识,它们的作用是这样的(引用官方例子):</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> config/locale/zh-CN.js</span>
module.exports =<span style="color: rgba(0, 0, 0, 1)"> {
</span>'Welcome back, %s!': '欢迎回来,%s!'<span style="color: rgba(0, 0, 0, 1)">,
};
ctx.__(</span>'Welcome back, %s!', 'Shawn'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> zh-CN => 欢迎回来,Shawn!</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> en-US => Welcome back, Shawn!</span></pre>
</div>
<p> </p>
<p>好了,一切准备就绪,如果需要在 Controller 中直接输出,需要调用 __ 方法进行转义,注意是两个下斜杠,不是让你填空...</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">class HomeController extends Controller {
async index() {
const ctx </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.ctx;
ctx.body </span>=<span style="color: rgba(0, 0, 0, 1)"> {
message: ctx.__(</span>'Welcome back, %s!'<span style="color: rgba(0, 0, 0, 1)">, ctx.user.name)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 或者使用 gettext,gettext 是 __ 函数的 alias</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> message: ctx.gettext('Welcome back', ctx.user.name)</span>
<span style="color: rgba(0, 0, 0, 1)"> user: ctx.user,
};
}
}</span></pre>
</div>
<p> </p>
<p>在视图模板中这样使用,假设你是 nunjucks 模板引擎:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>{{ page_title }}<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">></span>{{ __('Welcome back, %s!', page_content) }}<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p>
<p>经过处理后,我们将得到这样的页面效果:</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1140908/202002/1140908-20200211224718234-1038984811.png" alt=""></p>
<p> </p>
<p> </p>
<p>现在你也可以开发一个支持多语言的网站了,我所示例的都是基础代码,关于多语言支持请参考以下网址:</p>
<p>https://eggjs.org/zh-cn/core/i18n.html</p>
<p> </p>
<p>今天就到这里了,后续会出一些插件使用,或者是可以快速开发的方法。</p>
<p> </p>
<p> </p>
<p> </p>
<p>2020-2-11 写于揭阳</p>
<p><span style="color: rgba(51, 51, 51, 1); font-family: Verdana, Arial, Helvetica, sans-serif">转载请附上本博客地址:</span>https://www.cnblogs.com/chongsaid/<span style="color: rgba(51, 51, 51, 1); font-family: Verdana, Arial, Helvetica, sans-serif"> 或当前文章链接,否则视为侵犯著作权。</span></p><br><br>
来源:https://www.cnblogs.com/chongsaid/p/nodejs_eggframe_getStart.html
頁:
[1]