【问题标题】:Build a static site generator with Webpack使用 Webpack 构建静态站点生成器
【发布时间】:2019-01-05 17:49:51
【问题描述】:

我想使用 javascript 模板文字生成 html 内容,并在 Webpack 编译时输出静态 html 文件。我还需要一个具有热模块替换功能的开发服务器,可以处理 html、css 和 js 文件。

我需要 page1.js 在 HtmlWebpackPlugin 选项中:

new HtmlWebpackPlugin({
  template: './html-template.ejs',
  appMount: require('./src/views/page1')
})

然后我使用自定义的ejs模板html-template.ejs来导入生成的html内容:

<% if (htmlWebpackPlugin.options.appMount) { %>
<%= htmlWebpackPlugin.options.appMount %>
<% } %>

page1.js 看起来像这样:

const h1 = (text) => `<h1>${text}</h1>`;

module.exports = h1('Hello World');

请注意,page1.js未设置为入口点。唯一的入口点是 src/index.js(里面只有一个console.log 语句)。

当我运行webpack 时一切正常,dist/index.html 与 dist/main.js 一起生成。

如果我运行 webpack-dev-server 并尝试编辑 page1.js,浏览器会重新加载,但 html 内容不会更新。

关于如何使webpack-dev-server 和热模块替换适用于视图文件的任何想法?或者您有其他更好的解决方案来创建一个简单的静态站点生成器吗?

【问题讨论】:

  • 也许只使用 Jekyll。或者你想具体实施?
  • 而且听起来你的浏览器在 webpack 更新视图之前刷新了页面。好像你需要调用一些回调。
  • @DmitrySurin 我不想用 Jekyll,我想用 Webpack 创建一个静态站点生成器。现在唯一的问题是devServer,对我来说它看起来像一个错误:page1.js 没有正确连接到 HMR。我也尝试过使用 mini-html-webpack-plugin 和 webpack-serve,但错误仍然存​​在。

标签: javascript webpack webpack-dev-server html-webpack-plugin static-site


【解决方案1】:

您可以在 html 中执行此操作:

<%=require('./views/page1.js')%>

【讨论】:

  • 谢谢,这有助于解决问题。我想知道为什么 HtmlWebpackPlugin 选项中的 require page1.js 不能将其连接到 HMR,这似乎是一个错误。
【解决方案2】:

根据@petr 的回答,我确认直接在 html-template.ejs 内的 require page1.js 可以正常工作:

  • webpack.config.js 文件中的所有 require 调用都由 node 执行 - page1.js 将 不 连接到devServer
  • HtmlWebpackPlugin 模板中的所有 require 调用都由 webpack 执行 - page1.js 将正确连接到 devServer

请参阅this github 问题参考。

更进一步,您可以创建一个循环来自动加载所有视图并生成 html 文件:

webpack.config.js

  • 遍历每个 views 文件名并为该视图加载特定的 HtmlWebpackPlugin 配置
const viewsFiles = require('./readViewsFiles');
const viewsConfig = require('./webpack.views');

const pages = viewsFiles.map(pageName => {
  return viewsConfig({
    title: pageName,
    path: pageName == 'page1' ? '' : pageName,
    pageName
  });
});

module.exports = pages;

readViewsFiles.js

webpack.views.js

  • 返回一个新的 HtmlWebpackPlugin 实例
  • 如果是path == '',则为filename: 'index.html',否则为filename: 'page2/index.html'(对于每个视图名称,依此类推)
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = ({
  path = '',
  template = './html-template.ejs',
  title,
  pageName
} = {}) => ({
  plugins: [
    new HtmlWebpackPlugin({
      filename: `${path && path + '/'}index.html`,
      template,
      title,
      pageName
    })
  ]
});

html-template.ejs

  • 动态加载正确的views文件
<%= require(`./src/views/${htmlWebpackPlugin.options.pageName}.js`) %>

page1.js 和其他类似的视图文件

const h1 = (text) => `<h1>${text}</h1>`;

module.exports = h1('Hello World');

当您运行webpack 时,html 文件的 dist 文件夹中的结构将如下所示:

dist
│    index.html
│
│--- page2
│         index.html
│
│--- page3
          index.html

dist 文件夹被视为您服务器的根目录。

现在您可以在应用中实现路由器以在页面之间导航:

  • 为第 1 页设置指向 / 的链接:http://www.mywebsite.com/
  • 为第 2 页设置指向 /page2 的链接:http://www.mywebsite.com/page2

注意:您不必在链接中添加 index.html 即可在页面之间导航。使用此方法,您将不会在 url 末尾看到 .html 扩展名。

注意:您无法通过file:/// 协议查看您的应用,因为您的路由器链接设置为绝对路径,您必须使用本地或远程服务器。

【讨论】:

    猜你喜欢
    • 2020-05-28
    • 2017-09-21
    • 2017-04-11
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 2020-07-08
    • 1970-01-01
    相关资源
    最近更新 更多