webpack+模板引擎生成多个静态HTML

需求:

解决方案:

前面四个问题,在别的文章解释,其他的问题,咱们就在本文讨论

html 文件自动引入静态资源,转换路径

这个参考 将模板转换成 html 文件,html-webpack-plugin 在生成 html 文件时会自动引入资源文件,不过多入口时需要指定引用资源

生成多个页面

简单一点,配置多个入口,然后多整几个 new html-webpack-plugin。但是程序员的本质,是闪电。所以,copy 是不可能的,这辈子都不可能 copy 的,只能写写配置文件,然后批量生成这样子。所以我们可以这样做,先写一个配置文件,放置所有的页面的相关信息,然后写一个入口生成函数,批量生成入口。具体的做法看代码:

新建入口文件entrys.js

const path = require('path')

function resolve (dir) {
    return path.join(__dirname, '..', dir)
}

// 这里的配置信息,建议根据 html-webpack-plugin 的配置项信息编写,这样后续的工作会方便一些
let entrys = {
    globalParameters: {},
    list: [
        {
            entry: 'index',	// 入口名称
            entryPath: resolve('src/script/index.js'),	// 入口文件路径
            title: '默认页面',
            template: resolve('src/view/index.html'),	// 模板文件路径
        },
        {
            entry: 'home',
            entryPath: resolve('src/script/home.js'),
            title: '首页',
            template: resolve('src/view/home.html'),
        },
    ]
}

module.exports = entrys

然后编写生成配置的函数,需要生成两个东西,一个是 webpack 的入口对象,一个是 html-webpack-plugin 对象

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

function resolve (dir) {
    return path.join(__dirname, '..', dir)
}
const isProd = process.env.NODE_ENV === "production";

const defaults = {
    title: '',
    filename: '',
    template: '',
    chunks: '',
    templateParameters: {}
}
console.log(isProd);
// 构建入口
exports.buildEntry = function (entrys) {
    let entry = {};

    entrys.list.forEach(item => {
        if(!item.entry) return;

        entry[item.entry] = item.entryPath;
    })
    
    return entry;
}

// 构建生成 HTML 模板的入口
exports.buildTemplateEntry = function (entrys) {
    let arr = [],
        parameters = entrys.globalParameters;
        
    entrys.list.forEach(item => {
        let opt = Object.assign({}, defaults);

        opt.title = item.title;
        opt.filename = `view/${ item.filename || item.entry }.html`;
        opt.template = item.template;

        opt.templateParameters = item.templateParameters ? 
                Object.assign({}, parameters, item.templateParameters) :
                Object.assign({}, parameters);

        opt.chunks = item.entry ? [item.entry] : [];

        arr.push(new HtmlWebpackPlugin(opt));
    })

    return arr;
}

然后修改 webpack 的配置文件:

const entryHelp = require('./entryHelp')
const entrys = require('../config/entry')

{
	// ....

	entry: entryHelp.buildEntry(entrys),

	// 模板构建
	plugins: [
        ...entryHelp.buildTemplateEntry(entrys)
    ]
    
	// ....
}

到这里,生成多页面的配置就完成了。

热更新

热更新,顾名思义,修改文件后页面立马更新呈现修改后的内容。包括以下内容变更时的热更新:

  1. js 代码修改
  2. 静态资源修改(样式,图片)
  3. 模板修改
  4. webpack 或其他配置文件本身被修改

1 和 2 的变动,都可以直接使用 webpack 的热更新配置 devServer 处理就行,这里也还是上一下代码,还有什么疑问的话建议看官方文档 webpack热更新

配置文件的修改:

	devServer: {
	    hot: true
    },
	plugins: [
	
        // 模块热替换
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin(),
    ]

还需要在入口文件的末尾加上以下代码:

if (module.hot) {
    module.hot.accept()
}

然后以 webpack-dev-server 命令启动服务,就可以实现热更新了,

webpack-dev-server --config build/webpack.dev.conf.js

html 文件的变动,webpack 没有默认的监听处理,需要自己手动配置,做法是在构建完毕的回调里判断html是否有更新,有更新则往客户端推送更新,具体的配置信息如下:

	devServer: {
		// html 文件修改时刷新整个页面
	    before(app, server, compiler) {
	        const watchFiles = ['.html'];
	
	        compiler.hooks.done.tap('done', () => {
	            const changedFiles = Object.keys(compiler.watchFileSystem.watcher.mtimes);
	
	            if (
	                this.hot
	                && changedFiles.some(filePath => watchFiles.includes(path.parse(filePath).ext))
	            ) {
	                server.sockWrite(server.sockets, 'content-changed');
	            }
	        });
	    },
	}

webpack 配置的变更与其他配置文件变更实际上是无法热更新的,只能重启整个服务,虽然重启就那么两个操作

ctrl + c
npm run start

但是程序员皆是闪电,这点操作我也不愿意,能不能我保存配置就自动重启呢?答案是可以的!不过服务启动方式就得变一变了,不能再直接配置命令,然后直接启动,得使用 webpack api 调用的方式启动。首先我们得监听配置文件的变动,这里需要借助一下第三方插件 nodemon 我使用的版本 ^2.0.3。如果文件有变动,则重新执行 指定的 js 文件,nodemon 就是干这事儿的。

需要先写一个启动服务的配置 dev-server.js,以 api 调用的方式启动 webpack 热更新服务

const path = require('path')
const webpack = require('webpack')
const webpackDevServer = require('webpack-dev-server');

const baseConfig = require('../config/idnex')	// webpack 的配置文件,具体格式可以参考 vue-cli2 的模板的 conf/index.js 配置文件
const config = require('./webpack.dev.conf')
const compiler = webpack(config);

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

function resolve (dir) {
    return path.join(__dirname, '..', dir)
}

const devConfig = {
    contentBase: resolve('dist'),
    clientLogLevel: 'warning',
    hot: true,
    host: HOST || baseConfig.dev.host,
    port: PORT || baseConfig.dev.port,
    proxy: baseConfig.dev.proxyTable,

    // html 文件修改时刷新整个页面
    before(app, server, compiler) {
        const watchFiles = ['.html'];

        compiler.hooks.done.tap('done', () => {
            const changedFiles = Object.keys(compiler.watchFileSystem.watcher.mtimes);

            if (
                this.hot
                && changedFiles.some(filePath => watchFiles.includes(path.parse(filePath).ext))
            ) {
                server.sockWrite(server.sockets, 'content-changed');
            }
        });
    },
}

webpackDevServer.addDevServerEntrypoints(config, devConfig);

const server = new webpackDevServer(compiler, devConfig);

server.listen(devConfig.port, 'localhost', () => {
    console.log(`dev server listening on port ${ devConfig.port }`);
});

然后编写一个 nodemon 的配置文件,指定监听目录以及其他的一些配置,配置文件是 json 格式,但是这里为了展示,写成 js 格式
nodemon.json

{
    "ignore": [],	// 希望忽略的目录
    "watch": ["./build", "./config"]	// 监听目录
}

然后在 package.json 加一条脚本命令

"serve": "nodemon build/dev-server.js"

开发的时候,npm run serve 启动即可,如果修改了 build 或者 config 目录下的文件,则会重新执行对应的脚本,也就是重启 webpack 服务

开发模式接口代理

很多时候,接口服务器与 web 项目配置不在一个地方,这种时候就要配置接口代理,接口代理在 webpack 的 devServer.proxy 中配置,下面展示一下简单的代码,更多配置可以看官方文档的 接口代理

devServer: {
   	proxy: {
   		"/api": {
   			target: "https://other-server.example.com",	// 这里的接口地址一定要带上请求协议,不能只写域名
   		}
   	}
}

到这里,整个 webpack 生成多页面的开发环境搭建就完成了,项目的 demo 在 GitHub 上, dev 分支,有需要的可以拉下来看看,页面地址:https://github.com/just-a-developer/webpack-template-html/tree/dev

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值