async _renderFile({ fileSrc, fileDest, fileDestAlt, data }) {
      // site
      const site = data.site;
      // language
      const language = site.language && site.language.current;
      // src
      const pathIntermediate = await this.getPathIntermediate(language);
      const fileName = path.join(pathIntermediate, fileSrc);
      // dest
      const pathDist = await this.getPathDist(site, language);
      const fileWrite = path.join(pathDist, fileDest);
      // data
      data._filename = fileName;
      data._path = fileSrc.replace('.ejs', '');
      // env site
      data.env('site.path', data._path);
      // destFile for hot load
      let hotloadFile;
      if (data.article) {
        hotloadFile = `atom/${data.article.atomId}`;
        // update renderAt
        data.article.renderAt = new Date(this.ctx.bean.util.moment().unix() * 1000);
      } else {
        if ((this.app.meta.isTest || this.app.meta.isLocal) && fileDest.indexOf('.html') > -1) {
          hotloadFile = fileWrite;
          data.env('site.hotloadFile', hotloadFile);
        }
      }
      // load src
      let contentSrc = await fse.readFile(fileName);
      contentSrc = contentSrc ? contentSrc.toString() : '';
      // load includes of plugins
      const pluginIncludes = await this._loadPluginIncludes({ site, language });
      contentSrc = `${pluginIncludes}\n${contentSrc}`;
      // render
      const options = this.getOptions();
      options.filename = fileName;
      let content = await ejs.render(contentSrc, data, options);
      content = await this._renderEnvs({ data, content });
      content = await this._renderCSSJSes({ data, content });
      // write
      await fse.outputFile(fileWrite, content);
      // alternative url
      if (fileDestAlt && fileDestAlt !== fileDest) {
        const fileWriteAlt = path.join(pathDist, fileDestAlt);
        await fse.outputFile(fileWriteAlt, content);
      }
      // renderAt must be updated after file rendered
      if (data.article) {
        // update renderAt
        await this.ctx.model.query(
          `
          update aCmsArticle set renderAt=?
            where iid=? and atomId=?
          `,
          [data.article.renderAt, this.ctx.instance.id, data.article.atomId]
        );
      }
      // socketio publish
      if (hotloadFile) {
        await this._socketioPublish({ hotloadFile, article: data.article });
      }
    }
/*.ejs`);
      for (const item of indexFiles) {
        // data
        const data = await this.getData({ site });
        // path
        const _fileSrc = item.substr(pathIntermediate.length + 1);
        let _fileDest = _fileSrc.substr('main/index/'.length).replace('.ejs', '');
        if (_fileDest.indexOf('.') === -1) {
          _fileDest = `${_fileDest}.html`;
        }
        await this._renderFile({
          fileSrc: _fileSrc,
          fileDest: _fileDest,
          data,
        });
      }
    }

    async _writeSitemaps({ site, articles }) {
      // xml
      let xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
`;
      for (const article of articles) {
        const loc = this.getUrl(site, site.language && site.language.current, article.url);
        const lastmod = moment(article.updatedAt).format();
        xml += `  <url>
    <loc>${loc}</loc>
    <lastmod>${lastmod}</lastmod>
  </url>
`;
      }
      xml += '</urlset>';
      // save
      const pathDist = await this.getPathDist(site, site.language && site.language.current);
      const fileName = path.join(pathDist, 'sitemap.xml');
      await fse.writeFile(fileName, xml);
    }

    async _writeSitemap({ site, article }) {
      const loc = this.getUrl(site, site.language && site.language.current, article.url);
      const lastmod = moment(article.updatedAt).format();
      // load
      const pathDist = await this.getPathDist(site, site.language && site.language.current);
      const fileName = path.join(pathDist, 'sitemap.xml');
      let xml;
      const exists = await fse.pathExists(fileName);
      if (!exists) {
        xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>${loc}</loc>
    <lastmod>${lastmod}</lastmod>
  </url>
</urlset>`;
      } else {
        xml = await fse.readFile(fileName);
        xml = xml.toString();
        // remove
        const regexp = new RegExp(` {2}<url>\\s+<loc>[^<]*${article.url}[^<]*</loc>[\\s\\S]*?</url>[\\r\\n]`);
        xml = xml.replace(regexp, '');
        // append
        xml = xml.replace(
          '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
          `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>${loc}</loc>
    <lastmod>${lastmod}</lastmod>
  </url>`
        );
      }
      // save
      await fse.writeFile(fileName, xml);
    }

    async _renderStatic({ site }) {
      // static
      const pathIntermediate = await this.getPathIntermediate(site.language && site.language.current);
      const staticFiles = await eggBornUtils.tools.globbyAsync(`${pathIntermediate}/static/*