将含CSS与TypeScript的HTML页面打包为单HTML文件
需求:将HTML+CSS+TypeScript打包为单文件日志查看器
我有一个用于美化日志的HTML页面,包含CSS和TypeScript代码,希望把所有资源(CSS、TS编译后的JS、HTML)打包成单个独立HTML文件方便分享。试了Webpack但没搞定模板转换和资源内联,不限工具,求可行方案。
最小可复现示例
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>LogView</title> <link rel="stylesheet" href="logview.css"> <link rel="stylesheet" href="eyesymbols.css"> <link rel="stylesheet" href="DropDownButtonSymbolFonts.css"> <!-- apparently adding a font into a shadowdom does not work, so add it to head --> </head> <body> <div id="logview"></div> <div id="controls"></div> <script src="logview.js" async defer></script> <!-- Actual logic, logview.ts --> <script src="DropDownButton.js" async defer></script> <!-- Customelement, backed by DropDownButton.ts --> </body> </html>
当前Webpack配置
const path = require("path"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const HTMLInlineCSSWebpackPlugin = require("html-inline-css-webpack-plugin").default; module.exports = { mode: "development", // TODO: how should we switch this between development and production? devtool: false, // TODO: what is the correct setting here, to either do no transform or fast builds? entry: { dropdown: "./src/DropDownButton.ts", logview: "./src/logview.ts", //index: "./src/logview.html", }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[id].css", }), new HtmlWebpackPlugin({ filename: "logview.html", template: "./src/logview.html", chunks: [], inlineSource: ".(js|css)$", }), new HTMLInlineCSSWebpackPlugin(),//{filter: () => { return true; }}), ], module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", exclude: /node_modules/, }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, //"style-loader", "css-loader", ], type: "asset/inline", } ], }, resolve: { extensions: [ ".tsx", ".ts", ".js" ], }, output: { filename: "[name].js", path: path.resolve(__dirname, "dist"), clean: true, }, };
解决方案
方案一:修正Webpack配置实现单文件打包
你的配置问题在于未正确关联JS代码到HTML模板,且CSS内联逻辑冲突,调整如下:
1. 安装必要依赖
npm install webpack webpack-cli ts-loader html-webpack-plugin html-inline-script-webpack-plugin style-loader css-loader typescript --save-dev
2. 修改Webpack配置
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const HtmlInlineScriptPlugin = require("html-inline-script-webpack-plugin"); module.exports = (env) => { const isProduction = env.production === true; return { mode: isProduction ? "production" : "development", devtool: isProduction ? false : "eval-cheap-module-source-map", // 合并所有TS和CSS到入口chunk entry: { app: ["./src/logview.ts", "./src/DropDownButton.ts"], styles: ["./src/logview.css", "./src/eyesymbols.css", "./src/DropDownButtonSymbolFonts.css"] }, plugins: [ new HtmlWebpackPlugin({ filename: "logview.html", template: "./src/index.html", chunks: ["app", "styles"], // 生产模式自动压缩HTML minify: isProduction ? { collapseWhitespace: true, removeComments: true } : false }), // 内联所有JS和CSS到HTML new HtmlInlineScriptPlugin() ], module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", exclude: /node_modules/, }, // 用style-loader将CSS转为JS模块,方便后续内联 { test: /\.css$/, use: ["style-loader", "css-loader"], } ], }, resolve: { extensions: [".tsx", ".ts", ".js"], }, output: { filename: "[name].js", path: path.resolve(__dirname, "dist"), clean: true, }, }; };
3. 添加打包脚本
在package.json中添加命令,支持切换开发/生产模式:
{ "scripts": { "build:dev": "webpack", "build:prod": "webpack --env production" } }
方案二:用Parcel零配置快速实现
嫌Webpack配置麻烦的话,Parcel是零配置打包工具,直接支持单文件输出:
1. 安装Parcel
npm install parcel --save-dev
2. 执行打包
直接以HTML为入口,Parcel会自动处理所有依赖并内联:
npx parcel build src/index.html --no-source-maps --dist-dir dist
打包后dist/index.html就是包含所有内联资源的单文件。
方案三:手动合并(适合小型项目)
如果项目规模很小,也可以手动处理:
- 用
tsc编译TS为单个JS文件:tsc --outFile dist/bundle.js src/logview.ts src/DropDownButton.ts - 把所有CSS内容合并后,插入HTML头部的
<style>标签 - 把编译后的JS内容插入HTML的
<script>标签 - 保存为单个HTML文件即可
内容的提问来源于stack exchange,提问作者ted
相关产品推荐
相关产品推荐

