You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack输出HTML文件未保留原目录结构问题求助

问题:Webpack构建后HTML文件未保留原目录结构

项目背景

将基于Gulp+Foundation for Sites SCSS框架的法学案例书网站迁移至Webpack,对Webpack不熟悉。项目src目录结构如下:

/src
    /views
        /layouts
        /partials
        /pages
            /teaching
                4个内部HTML文件
            index.html
            2个其他顶级HTML文件

注:项目入口为/src/assets/js/app.ts,该文件内通过@import引入/src/assets/scss/app.scss,这部分构建正常。

当前HTML构建配置

1. html-webpack-plugin 配置

const htmlPages = glob.sync('./src/views/pages/**/*.html').map(page => {
    const filename = path.basename(page);
    return new HtmlWebpackPlugin({
        template: page,
        filename: filename,
        inject: true
    });
});

2. Nunjucks模板加载规则

// Nunjucks templates
{
    test: /\.html$/,
    // exclude: /src\/views\/pages\/.*\.html$/, /* <- break rule experiment */
    use: [
        {
            loader: 'html-loader',
            options: {
                sources: false,
                minimize: PRODUCTION,
                esModule: false
            }
        },
        {
            loader: 'nunjucks-html-loader',
            options: {
                searchPaths: [
                    path.resolve(__dirname, 'src/views/')
                ],
                context: {
                    // Global context variables for templates
                    PRODUCTION: PRODUCTION
                }
            }
        }
    ]
},

3. 插件引入

plugins: [
    ...htmlPages
]

问题现象

期望dist目录结构:

/dist
    /teaching
        4个HTML文件
     index.html
     2个其他HTML文件

实际生成结果:7个HTML文件全部直接输出在dist根目录,未保留原目录结构。

原因分析

问题核心出在html-webpack-plugin的filename配置上:你使用path.basename(page)提取文件名,这个方法只会返回文件的纯名称(比如/src/views/pages/teaching/file.html会被提取为file.html),完全丢弃了文件所在的目录层级,导致所有文件都被输出到dist根目录。

加载器配置和目录结构问题无关——之前修改正则或添加exclude导致模板内容丢失,是因为破坏了模板的处理流程,但并非目录结构异常的原因。

解决方案

计算每个HTML文件相对于src/views/pages的相对路径,将该路径作为filename的值,即可保留原目录结构。修改后的htmlPages代码如下:

const pagesRoot = path.resolve(__dirname, 'src/views/pages');
const htmlPages = glob.sync('./src/views/pages/**/*.html').map(page => {
    // 获取文件相对于pages根目录的路径
    const relativePath = path.relative(pagesRoot, page);
    return new HtmlWebpackPlugin({
        template: page,
        filename: relativePath,
        inject: true
    });
});

修改后,src/views/pages/teaching/file.html对应的relativePath为teaching/file.html,输出时会自动生成dist/teaching/file.html;顶级的index.html则直接输出到dist/index.html,完全符合预期结构。

内容的提问来源于stack exchange,提问作者Frank Burleigh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:12:49