使用html-webpack-plugin对HTML文件进行预处理

原文地址:https://segmentfault.com/a/1190000021518323
作者:Fw恶龙
本文首发于:思否

一、前言

先整理一波之前和webpack相关的文章:

  • 使用Webpack对CSS文件进行后处理
  • 基于Webpack的CSS Sprites实现方案
  • Stylus系列——webpack-spritesmith配合stylus使用示例

继以上第三篇文章后很大程度上提高了CSS的开发效率,但是仍存在以下遗留问题:

  1. 在开发一个有多页面的项目时,CSS文件部分需要复用,部分需要各自页面引用,之前是直接打包至一个文件,目前需要修改下webpack的路径配置;
  2. 在CSS中引用的图片可以进行添加版本号、转base64等处理,而HTML中引用的CSS仍需要手动添加版本号,而且img标签的图片无法通过一系列处理;
  3. 每次开发完毕都需要人工去压缩处理图片,过程繁琐浪费时间;

为了降低和之前文章的耦合度,还有部分更新内容,故重新进行配置,和本文相关的内容会进行注释,其他配置的相关内容可以参考以上文章。

二、项目配置

1. 目录结构预览

+ node_modules      // npm install 生成
+ src               // 开发目录(自行创建)- index.ejs             // 用于生成index.html的模板文件+ css- sprite.styl       // webpack-spritesmith生成- index.styl- function.styl     // styl个人常用函数+ images- sprite.png        // webpack-spritesmith生成+ sprite            // 雪碧图放置文件夹..png..png+ js+ index.js
+ dist              // 代码产出目录– index.html    // html-webpack-plugin生成+ css- index.css+ images- icon.png+ js- index.js+ otherindex.js
– package.json      // npm init 生成
– package-lock.json // npm install 生成
- postcss.config.js // 自行创建
– webpack.config.js // 自行创建

2. 初始化项目

npm init

3. package.json

{"name": "cwwebpack","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","start": "webpack --mode development"},"author": "","license": "ISC","devDependencies": {"autoprefixer": "^9.1.2","clean-webpack-plugin": "^1.0.0","css-loader": "^1.0.0","cssnano": "^4.0.5","file-loader": "^1.1.11","html-webpack-plugin": "^3.2.0","image-webpack-loader": "^6.0.0","postcss-loader": "^3.0.0","postcss-sorting": "^4.0.1","stylus": "^0.54.5","url-loader": "^1.1.1","webpack": "^4.17.0","webpack-cli": "^3.1.2","webpack-spritesmith": "^0.5.4"},"dependencies": {"mini-css-extract-plugin": "^0.4.1","stylus-loader": "^3.0.2"},"browserslist": ["> 1%","last 2 versions","not ie <= 8","ios >= 8","android >= 4.0"]
}

4. 安装相关modules

npm install

5. webpack.config.js

var path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const SpritesmithPlugin = require('webpack-spritesmith');
const HtmlWebpackPlugin = require('html-webpack-plugin');var templateFunctionStylSprite = function(data) {var sharedRem = '.ico\n    display: inline-block\n    background-image: url("I")\n    background-size: Dpx Hpx'.replace('I', data.sprites[0].image).replace('D', data.sprites[0].total_width).replace('H', data.sprites[0].total_height);var perSpriteRem = data.sprites.map(function(sprite) {return '.ico-N\n    width: Wpx\n    height: Hpx\n    background-position: Xpx Ypx'.replace('N', sprite.name.replace(/_/g, '-')).replace('W', sprite.width).replace('H', sprite.height).replace('X', sprite.offset_x).replace('Y', sprite.offset_y);}).join('\n');return sharedRem + '\n' + perSpriteRem;
};module.exports = {entry: {    // 入口文件,若有多个入口文件可以继续创建,用于解决前言中提到的第一点'index': __dirname + "/src/js/index.js"},output: {path: __dirname + "/dist", //打包后的文件存放的地方filename: "js/other/[name].js" //打包后输出文件的文件名},watch: true, //开启自动编译module: {rules: [{test: /\.styl$/,use: [{loader: MiniCssExtractPlugin.loader,options: {publicPath: "../"}}, {loader: "css-loader"}, {loader: "postcss-loader"}, {loader: "stylus-loader"}]},{test: /\.(png|svg|jp?g|gif)$/,use: [{loader: 'url-loader',options: {limit: 8192,name: 'images/[name].[ext]?v=[hash:8]'}}, {loader: 'image-webpack-loader',     // 图片压缩,用于解决前言中提到的第三点options: {mozjpeg: {progressive: true,quality: 90},// optipng.enabled: false will disable optipngoptipng: {enabled: true,},pngquant: {quality: [0.90, 1.00],speed: 4},gifsicle: {interlaced: false,}}}]}]},plugins: [new CleanWebpackPlugin(['dist/css', 'dist/images'],{root: __dirname,verbose: true,dry: true}),new SpritesmithPlugin({src: {cwd: path.resolve(__dirname, 'src/images/sprite'),glob: '*.png'},target: {image: path.resolve(__dirname, 'src/images/sprite.png'),css: [[path.resolve(__dirname, 'src/css/sprite.styl'), {format: 'function_based_template'}]]},customTemplates: {'function_based_template': templateFunctionStylSprite},apiOptions: {cssImageRef: '../images/sprite.png'},spritesmithOptions: {algorithm: 'binary-tree',padding: 2}}),new MiniCssExtractPlugin({filename: "css/[name].css?v=[hash:8]",chunkFilename: "[id].css"}),new HtmlWebpackPlugin({         // 打包html文件,用于解决前言中提到的第二点template:'./src/index.ejs', // 模板文件路径filename: 'index.html',     // 生成的文件名title: 'My App',            // 页面titlechunks: ['index'],          // 需要引入的入口文件,根据entry的入口文件进行配置,会将其生成的css和js插入到模板中inject: false,              // 不插入生成的js文件,只是单纯的生成一个html文件,由于个人开发需求,js不需要引入,需要单独开发minify:{                    //压缩HTML文件,常用属性如下removeComments: false,                  // 移除HTML中的注释collapseWhitespace: false,              // 删除空白符preserveLineBreaks: false,              // 删除换行removeStyleLinkTypeAttributes: true,    // type="text/css"从style和link标签中删除removeScriptTypeAttributes: true        // type="text/javascript"从script标签中删除}})],
};

6. postcss.config.js

module.exports = {plugins: [require('autoprefixer'),require('cssnano')({preset: 'default',}),require('postcss-sorting')({'properties-order': 'alphabetical'})]
}

7. src/js/index.js

import '../css/index.styl';

8. src/css/index.styl

@import "function.styl"
@import "sprite.styl"

9. src/index.ejs

关于为何使用ejs后缀名,可以参考以下关于html-webpack-plugin属性及其配置的说明。

<!DOCTYPE html>
<html lang="zh-CN"><head><% /* 根据webpack.config.js中的title设置标题 */ %><title><%= htmlWebpackPlugin.options.title %></title><% /* 由于个人需求,不需要插入js,只需要css */ %><% for (var css in htmlWebpackPlugin.files.css) { %><link href="<%=htmlWebpackPlugin.files.css[css] %>" rel="stylesheet"><% } %></head><body><% /* html中使用到的图片需以如下方式插入,才可进行图片的一系列处理 */ %><img src="<%=require('./images/home_bg.jpg')%>" alt="" style="width: 100px;"></body></html>

10. 执行打包命令

npm start

三、html-webpack-plugin属性及其配置

  • html处理:Github|html-webpack-plugin
  • html压缩:Github|html-minifier
  • html-webpack-plugin用法全解(翻译很全)
  • html-webpack-plugin详解(有写到在ejs中自定义引用文件的方式)

四、image-webpack-loader属性及其配置

  • Github|image-webpack-loader

五、遗留问题

  • 关于html压缩html-minifier的配置,提供了可以删除空白和保留换行的配置,但是我想要保留换行的同时保持html文档结构,目前没找到处理方法。(20200408-可以使用html-beautify-webpack-plugin,后续文章会进行讲解)
  • 关于图片压缩的参数还没调整到较优的方案。

作者:Fw恶龙

喜欢 0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/472947.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二、ActiveMQ安装

ActiveMQ安装 一、相关环境二、安装Java8三、下载安装包四、启动五、其他命令六、开放端口七、后台管理 一、相关环境 环境&#xff1a;Centos7.9安装ActiveMQ版本&#xff1a;5.15.9JDK8 二、安装Java8 安装教程&#xff1a;https://qingsi.blog.csdn.net/article/details/…

软件工程师,OpenAI Sora驾到,快来围观

概述 近期&#xff0c;OpenAI在其官方网站上公布了Sora文生视频模型的详细信息&#xff0c;展示了其令人印象深刻的能力&#xff0c;包括根据文本输入快速生成长达一分钟的高清视频。Sora的强大之处在于其能够根据文本描述&#xff0c;生成长达60秒的视频&#xff0c;其中包含&…

字符串拼接 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 给定 M 个字符( a-z ) &#xff0c;从中取出任意字符(每个字符只能用一次)拼接成长度为 N 的字符串&#xff0c;要求相同的字符不能相邻。 计算出给定的字符列表…

平时积累的FPGA知识点(10)

平时在FPGA群聊等积累的FPGA知识点&#xff0c;第10期&#xff1a; 41 ZYNQ系列芯片的PL中使用PS端送过来的时钟&#xff0c;这些时钟名字是自动生成的吗&#xff1f; 解释&#xff1a;是的。PS端设置的是ps_clk&#xff0c;用report_clocks查出来的时钟名变成了clk_fpga_0&a…

JavaScript设计模式与开发实战

JavaScript设计模式与开发实践 第一章、面向对象的JavaScript 1.1 多态 类似java面向对象&#xff0c;通过继承共有特征&#xff0c;来实现不同方法。JavaScript的多态就是把“做什么”和“谁去做”分离&#xff0c;消除类型间的耦合关系。 他的作用就是把过程化的条件分支…

解决LeetCode编译器报错的技巧:正确处理位操作中的数据类型

一天我在leetcode上刷题时&#xff0c;遇到了这样的题目&#xff1a; 随即我写了如下的代码&#xff1a; int convertInteger(int A, int B) {int count 0;int C A ^ B;int flag 1;while(flag){if (C & flag){count;}flag<<1;}return count;} 但LeetCode显示如下…

07-k8s中secret资源02-玩转secret

一、回顾secret资源的简单实用 第一步&#xff1a;将想要的数据信息【key&#xff1a;value】中的value值&#xff0c;使用base64编码后&#xff0c;写入secret资源清单中&#xff1b; 第二步&#xff1a;创建secret资源&#xff1b; 第三步&#xff1a;pod资源引用secret资源&…

建造者模式-Builder Pattern

原文地址:https://jaune162.blog/design-pattern/builder-pattern/ 引言 现在一般大型的业务系统中的消息通知的形式都会有多种,比如短信、站内信、钉钉通知、邮箱等形式。虽然信息内容相同,但是展现形式缺不同。如短信使用的是纯文本的形式,钉钉使用的一般是Markdown的形…

【研究生复试】计算机软件工程人工智能研究生复试——资料整理(速记版)——JAVA

1、JAVA 2、计算机网络 3、计算机体系结构 4、数据库 5、计算机租场原理 6、软件工程 7、大数据 8、英文 自我介绍 1. Java 1. 和 equals的区别 比较基本数据类型是比较的值&#xff0c;引用数据类型是比较两个是不是同一个对象&#xff0c;也就是引用是否指向同 一个对象&…

C#,计算几何,贝塞耳插值(Bessel‘s interpolation)的算法与源代码

Friedrich Wilhelm Bessel 1 贝塞耳插值&#xff08;Bessels interpolation&#xff09; 首先要区别于另外一个读音接近的插值算法&#xff1a;贝塞尔插值&#xff08;Bzier&#xff09;。 &#xff08;1&#xff09;读音接近&#xff0c;但不是一个人&#xff1b; &#x…

【二十一】【C++】模版特化

模版的参数 类型模板参数 类型模板参数允许在定义模板时指定一个占位符&#xff0c;这个占位符在模板实例化时将被具体的类型替换。这使得我们能够编写与类型无关的通用代码。例如&#xff0c;标准库中的 std::vector<T> 使用一个类型模板参数 T&#xff0c;这意味着你…

transformer-Attention is All You Need(一)

1. 为什么需要transformer 循环模型通常沿输入和输出序列的符号位置进行因子计算。通过在计算期间将位置与步骤对齐&#xff0c;它们根据前一步的隐藏状态和输入产生位置的隐藏状态序列。这种固有的顺序特性阻止了训练样本内的并行化&#xff0c;这在较长的序列长度上变得至关重…