使用 Webpack 构建静态站点生成器
Build a static site generator with Webpack
我想使用 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 与 [=34 一起生成=]dist/main.js.
如果我 运行 webpack-dev-server
并尝试编辑 page1.js,浏览器会重新加载,但 html 内容不会更新。
关于如何使 webpack-dev-server
和热模块替换适用于视图文件的任何想法?或者您有任何其他更好的解决方案来创建简单的静态站点生成器吗?
您可以在 html 中执行此操作:
<%=require('./views/page1.js')%>
在@petr 回答之后,我确认直接在 html-template.ejs[=97 中要求 page1.js =] 工作正常:
- webpack.config.js 文件中的所有
require
调用都由 node - [ 执行=137=] 不会 连接到 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
- Return 所有 views 不带扩展名的文件名的数组列表,例如:
['page1','page2','page3']
- 见How do you get a list of the names of all files present in a directory in Node.js?
webpack.views.js
- Return 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
dist 文件夹中 html 文件的结构如下所示:
dist
│ index.html
│
│--- page2
│ index.html
│
│--- page3
index.html
dist 文件夹被认为是您服务器的根目录。
现在您可以在您的应用程序中实施路由器以在页面之间导航:
- 将第 1 页的 link 设置为
/
:http://www.mywebsite.com/
- 将第 2 页的 link 设置为
/page2
:http://www.mywebsite.com/page2
注意:您不必将 index.html 添加到 link 即可在页面之间导航。使用此方法,您将不会在 url.
末尾看到 .html 扩展名
注意:您无法通过 file:///
协议查看您的应用,因为您的路由器 link 设置为 绝对路径 ,您必须使用本地或远程服务器。
我想使用 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 与 [=34 一起生成=]dist/main.js.
如果我 运行 webpack-dev-server
并尝试编辑 page1.js,浏览器会重新加载,但 html 内容不会更新。
关于如何使 webpack-dev-server
和热模块替换适用于视图文件的任何想法?或者您有任何其他更好的解决方案来创建简单的静态站点生成器吗?
您可以在 html 中执行此操作:
<%=require('./views/page1.js')%>
在@petr 回答之后,我确认直接在 html-template.ejs[=97 中要求 page1.js =] 工作正常:
- webpack.config.js 文件中的所有
require
调用都由 node - [ 执行=137=] 不会 连接到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
- Return 所有 views 不带扩展名的文件名的数组列表,例如:
['page1','page2','page3']
- 见How do you get a list of the names of all files present in a directory in Node.js?
webpack.views.js
- Return 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
dist 文件夹中 html 文件的结构如下所示:
dist
│ index.html
│
│--- page2
│ index.html
│
│--- page3
index.html
dist 文件夹被认为是您服务器的根目录。
现在您可以在您的应用程序中实施路由器以在页面之间导航:
- 将第 1 页的 link 设置为
/
:http://www.mywebsite.com/
- 将第 2 页的 link 设置为
/page2
:http://www.mywebsite.com/page2
注意:您不必将 index.html 添加到 link 即可在页面之间导航。使用此方法,您将不会在 url.
末尾看到 .html 扩展名注意:您无法通过 file:///
协议查看您的应用,因为您的路由器 link 设置为 绝对路径 ,您必须使用本地或远程服务器。