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

梦

一、前言

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

继以上第三篇文章后很大程度上提高了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
        + other
            index.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 optipng
                        optipng: {
                          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',            // 页面title
            chunks: ['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属性及其配置

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

五、遗留问题

  • 关于html压缩html-minifier的配置,提供了可以删除空白和保留换行的配置,但是我想要保留换行的同时保持html文档结构,目前没找到处理方法。
  • 关于图片压缩的参数还没调整到较优的方案。
Image placeholder
peterq
未设置
  99人点赞

没有讨论,发表一下自己的看法吧

推荐文章
HTML文字怎么插入下划线?

在HTML中想要给文字加下划线可以使用标签来实现。下划线标签的语法:我被加下划线了来看个完整代码的用法实例: 这里是HTML中文网! HTML中文网网址:www.html.

HTML文本标签与格式标签笔记

用画图工具量出坐标,通过左上角的点和右下角的点相连

Stylus系列——webpack-spritesmith配合stylus使用示例

一、前言基于Webpack的CSSSprites实现方案,若是直接在html中调用雪碧图图标已经很方便,但是实际开发过程可能遇到需要在伪元素中使用雪碧图,或者需要hover切换另一个图标,这种情况下就

css预处理器是什么意思?

css预处理器是什么意思?css预处理器用来定义一种新的语言,完全兼容css语法,它为css增加了一些编程的特性,比如变量、函数、逻辑控制。css预处理器编写的css不能直接被浏览器识别,需要编译生成

css预处理器怎么用?

css预处理器的用法:首先我们需要安装css预处理器,这里以less为例,讲解css预处理器的安装以及简单使用。1、使用npm命令安装lesscss预处理器npminstall-gless推荐学习:N

innerHTML与jquery里的html()区别?

innerHTML与jquery里的html()区别?●html()可以设置tbody、tr这些只读标签,而innerHTML在低版本IE下不行;jQuery的html()做了些容错处理,原生的Dom

webpack中css的url报错?

webpack中css的url报错?css-loader://打包样式中背景图 { test:/\.(png|jpg)$/, loader:"url-loader?limit=8192&name=im

基于Webpack的css sprites实现方案

一、前言关于csssprites(雪碧图/精灵图)的几种实现方案可以参考浅谈CSSSprites雪碧图应用。本文主要讨论基于webpack的csssprites实现方案。由于使用webpack时会涉及

react中的webpack是什么?

Webpack是一个开源的前端打包工具。Webpack提供了前端开发缺乏的模块化开发方式,将各种静态资源视为模块,并从它生成优化过的代码。Webpack可以从终端、或是更改webpack.config

Java Web html无法引用css?

JavaWebhtml无法引用css?javaweb中html无法引用css是因为css文件放置的位置不正确,css文件应该放在与WEB-INF同级目录,而不是WEB-INF文件夹内。(相关课程推荐:

WebAssembly前瞻及用C/C++写HTML和Hanjst汉吉斯特

2019年12月16日,北京下了今冬第二场雪❄️,不大不小。年终岁尾,国际上几大软件及互联网公司(Google、Microsoft、Apple和Mozilla)拉上互联网标准化机构W3C发布了WebA

GoWeb教程_08.2. WebSocket

WebSocket是HTML5的重要特性,它实现了基于浏览器的远程socket,它使浏览器和服务器可以进行全双工通信,许多浏览器(Firefox、GoogleChrome和Safari)都已对此做了支

GoWeb教程_ 07.1. XML 处理

XML作为一种数据交换和信息传递的格式已经十分普及。而随着Web服务日益广泛的应用,现在XML在日常的开发工作中也扮演了愈发重要的角色。这一小节,我们将就Go语言标准包中的XML相关处理的包进行介绍。

Python可视化 | Seaborn5分钟入门(二)——barplot&countplot&pointplot

微信公众号:「Python读财」如有问题或建议,请公众号留言Seaborn是基于matplotlib的Python可视化库。它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matp

Pandas数据处理三板斧——map、apply、applymap详解

微信公众号:「Python读财」如有问题或建议,请公众号留言在日常的数据处理中,经常会对一个DataFrame进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的map、apply和apply

html找不到css文件怎么解决

html找不到css文件怎么解决如果你在引用css文件时,使用了错误的文件路径,就会导致引用失效。解决方法就是填写正确的css文件路径。下面我们学习下HTML填写路径的两种方法。(推荐学习:HTML视

GoWeb教程_04.5. 处理文件上传

你想处理一个由用户上传的文件,比如你正在建设一个类似Instagram的网站,你需要存储用户拍摄的照片。这种需求该如何实现呢? 要使表单能够上传文件,首先第一步就是要添加form的enctype属性,

基于 Hyperf 实现 RabbitMQ + WebSocket 消息推送

#介绍 基于Hyperf+WebSocket+RabbitMQ实现的一个简单大屏幕的消息推送。 #思路 利用WebSocket协议让客户端和服务器端保持有状态的长链接,保存链接上来的客户端id。订阅发

GoWeb教程_05.5. 使用 Beego orm 库进行 ORM 开发

beegoorm是我开发的一个Go进行ORM操作的库,它采用了Gostyle方式对数据库进行操作,实现了struct到数据表记录的映射。beegoorm是一个十分轻量级的GoORM框架,开发这个库的本

beego 使用 coding 的 webhook 2.0 进行自动部署

beego使用coding的webhook2.0进行自动部署本文介绍beego在coding上如果使用webhook2.0进行自动部署。coding的webhook1.0教程coding平台端的设置这

GoWeb教程_08.0. Web 服务

Web服务可以让你在HTTP协议的基础上通过XML或者JSON来交换信息。如果你想知道上海的天气预报、中国石油的股价或者淘宝商家的一个商品信息,你可以编写一段简短的代码,通过抓取这些信息然后通过标准的

GoWeb教程_13.0. 如何设计一个 Web 框架

前面十二章介绍了如何通过Go来开发Web应用,介绍了很多基础知识、开发工具和开发技巧,那么我们这一章通过这些知识来实现一个简易的Web框架。通过Go语言来实现一个完整的框架设计,这框架中主要内容有第一

GoWeb教程_14.0. 扩展 Web 框架

第十三章介绍了如何开发一个Web框架,通过介绍MVC、路由、日志处理、配置处理完成了一个基本的框架系统,但是一个好的框架需要一些方便的辅助工具来快速的开发Web,那么我们这一章将就如何提供一些快速开发

react-native中IOS的webview和js层通信 - UIWebview

前言在9012的最后一篇写到了在rn中安卓的webview的通信原理,而作为0202年的第一篇,继续讨论上年rn中webview通信剩下的部分。背景:对于webview,了解过的人都知道在ios端会存

重启大法失效?详述Oracle11g因JDBC bug引发异常Library Cache Lock等待处理事件

墨墨导读:在Oracle11g版本中可能出现由于JDBCbug导致sql绑定变量无法共享,过期游标过多的情况,此时如果发生大量并发业务,很有可能造成异常librarycachelock等待事件,造成数