基于nodejs服务端web组件化开发(六、全局配置)

60 阅读2分钟

六、全局配置

上节对代码结构已经构建出来了,但是对于一些全局通用的设置应进行下包装 首先看看 html 文档,并对结构进行分析

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <!-- meta -->
    <title><!-- 标题 --></title>
    <!-- 全局style -->
    <!-- 组件style -->
  </head>
  <body>
    <!-- 结构内容 -->
    <!-- 全局js -->
    <!-- 组件js -->
  </body>
</html>

从上述的分析可以先定义个 html 模板,把坑挖好,由于这是项目全局模板"index.tpl",应放在根目录

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    { meta }
    <title>{ title }</title>
    { style } { css }
  </head>
  <body>
    { body } { script } { js }
  </body>
</html>

全局通用配置,这个东西也因放在根目录

// hcdr.config.js 新增
module.exports = {
  metas: [
    { name: "description", content: "xxx网站-专业的综合网上购物商城,..." },
    { name: "Keywords", content: "网上购物,网上商城,手机,..." }
  ],
  title: "xx网站",
  styles: ["css/reset.css"],
  scripts: ["js/jquery.js"]
}

考虑到每个页面都有一些静态设置,而且要和全局通用的配置合并, 好了先弄个合并方法再说,这个就是拼接代码的地方了

// hcdr/compose.js 新增
const fs = require("fs")
const path = require("path")

const TPL_FILE_PATH = path.resolve(process.cwd(), "index.tpl")
const CONFIG_FILE_PATH = path.resolve(process.cwd(), "hcdr.config.js")

const template = `
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    { meta }
    <title>{ title }</title>
    { style } { css }
  </head>
  <body>
    { body } { script } { js }
  </body>
</html>
`
// 获取模板
const htmlTemplate = fs.existsSync(TPL_FILE_PATH)
  ? fs.readFileSync(TPL_FILE_PATH, "utf-8")
  : template

// 获取全局配置
const sysConfig = fs.existsSync(CONFIG_FILE_PATH)
  ? require(CONFIG_FILE_PATH)
  : { metas: [], title: "", styles: [], scripts: [] }

// 合并配置
function merge(config = {}) {
  return {
    meta: [...sysConfig.metas, ...(config.metas || [])]
      .map(item => `<meta name="${item.name}" content="${item.content}">`)
      .join("\n"),
    title: config.title || sysConfig.title,
    style: [...sysConfig.styles, ...(config.styles || [])]
      .map(item => `<link rel="stylesheet" href="${item}">`)
      .join("\n"),
    script: [...sysConfig.scripts, ...(config.scripts || [])]
      .map(item => `<script src="${item}"></script>`)
      .join("\n")
  }
}

// 返回组合后的代码
module.exports = ({ config = {}, strHtml = "", strCss = "", strJs = "" }) => {
  // 替换模板的变量
  const tplReplace = (template, obj) =>
    template.replace(/\{(.*?)\}/g, (_, key) => obj[key.trim()])

  let params = {
    ...merge(config),
    body: strHtml,
    css: `<style>${strCss}</style>`,
    js: `<script>${strJs}</script>`
  }

  let code = tplReplace(htmlTemplate, params)

  return code
}

于是我们需对返回字符串进行修改了

// hcdr/index.js 修改
// 引入 compose 发哈
const compose = require("./compose")

// 函数最后补充一个参数 config
function render(component, data, css, config) {
  let strHtml = component(data || {}, css || {})
  let strCss = container.style.filter(str => str).join("\n")
  let strJs = container.script
    .filter(fn => fn)
    .map(fn => {
      const str = fn.toString()
      let start = str.indexOf("{")
      let end = str.lastIndexOf("}")
      str = str.substring(start + 1, end).trim()
      return str ? `;(function(){${str}})()` : ""
    })
    .filter(fn => fn)

  // 修改返回内容
  let code = compose({ config, strHtml, strCss, strJs })
  // 晴空下缓存
  container = { style: [], script: [] }
  return code
}

添加首页配置如下

// test2.js 修改

// ...

const code = render(Layout, { slot: Home() }, null, {
  title: "首页-xxx网站",
  styles: ["css/index.css"],
  scripts: ["js/index.js"]
})
console.log(code)

运行,这回这个结构就规范了

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <!-- meta -->
    <meta name="description" content="xxx网站-专业的综合网上购物商城,..." />
    <meta name="Keywords" content="网上购物,网上商城,手机,..." />
    <!-- 标题 -->
    <title>首页-xxx网站</title>
    <!-- 全局style -->
    <link rel="stylesheet" href="css/reset.css" />
    <link rel="stylesheet" href="css/index.css" />
    <!-- 组件style -->
    <style>
      .navbar {
        color: red;
      }
      .navbar {
        color: blue;
      }
    </style>
  </head>
  <body>
    <!-- 结构内容 -->
    <div id="app">
      <header><div class="header">头部</div></header>
      <nav><div class="navbar">导航</div></nav>
      <main>undefined</main>
      <footer><div>底部</div></footer>
    </div>
    <!-- 全局js -->
    <script src="js/jQuery.js"></script>
    <script src="js/index.js"></script>
    <!-- 组件js -->
    <script>
      ;(function () {
        console.log("我是在游览器执行的脚本.")
      })()
    </script>
  </body>
</html>

至此,我们可以看到了生成像样的代码了。 我们一直都是用控制台进行测试,下节我们搭建服务器进行项目搭建看看效果...