使用html-webpack-plugin對HTML文件進行預處理

夢

1、前言

先整理一波以前和webpack相關的文章:javascript

繼以上第三篇文章後很大程度上提升了CSS的開發效率,可是仍存在如下遺留問題:css

  1. 在開發一個有多頁面的項目時,CSS文件部分須要複用,部分須要各自頁面引用,以前是直接打包至一個文件,目前須要修改下webpack的路徑配置;
  2. 在CSS中引用的圖片能夠進行添加版本號、轉base64等處理,而HTML中引用的CSS仍須要手動添加版本號,並且img標籤的圖片沒法經過一系列處理;
  3. 每次開發完畢都須要人工去壓縮處理圖片,過程繁瑣浪費時間;

爲了下降和以前文章的耦合度,還有部分更新內容,故從新進行配置,和本文相關的內容會進行註釋,其餘配置的相關內容能夠參考以上文章。html

2、項目配置

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屬性及其配置的說明。java

<!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

3、html-webpack-plugin屬性及其配置

4、image-webpack-loader屬性及其配置

5、遺留問題

  • 關於html壓縮html-minifier的配置,提供了能夠刪除空白和保留換行的配置,可是我想要保留換行的同時保持html文檔結構,目前沒找處處理方法。
  • 關於圖片壓縮的參數還沒調整到較優的方案。
相關文章
相關標籤/搜索