Skip to content

Webpack 3.x 学习-第三天 #7

@shushu2013

Description

@shushu2013

Webpack 学习第五步

前言提示

说明

经过前两天的学习总结,我们把配置文件分为 开发环境配置生产环境配置,因为 开发环境配置 相对简单,所有在之后的学习中我们统一修改的是 生产环境配置 文件。

避免由于版本号带来的坑

在使用各种 Webpack 的插件和 Loader 时,一定要注意使用的版本号,因为不同版本有些配置项可能不同。

那如何找到对应版本的文档呢?

方法一:

去项目的 GitHub 仓库地址,可以选择代码的 Branche 中的 Tags 标签来选择对应的代码版本,一般都有对应的使用文档。

方法二:

如果方法一不起作用,那可以去项目的官方网站,结合其中的文档和更新日志来查看对应版本有哪些改变的地方。

1、处理图片

需求:
图片可能在 CSS, JS, HTML 中使用,如下所示

// 在 css 中使用图片
.bg {
    background-image: url('../image/index/001.jpg');
}

// 在 js 中使用图片
function addImg() {
    var imgUrl = require('../image/index/001.jpg');
    var img = document.createElement('img');
    img.src = imgUrl;

    document.body.appendChild(img);
}

// 在 html 中使用图片
<img src="image/index/001.jpg" >

我们需要把这些图片提取出来,并且放到指定目录下。

1.1 使用到的插件:

file-loader:解析提取 CSS, JS 中的图片
url-loader:类似 file-loader,可设置把图片文件转为 Base64 的格式写入 CSSJS
html-withimg-loader:解析提取 HTML 中的 img 标签引用的图片

参考资料:

file-loader GitHub 地址
url-loader GitHub 地址
html-withimg-loader GitHub 地址

1.2 使用 file-loader

安装:

cnpm i -D file-loader

配置:

module.exports = {

    // ... 省略其他配置项
    
    // 模块:例如转换 es6, less, 图片转换等...
    module: {
        rules:[
        
            // ...省略其他配置项
            
            {
                test: /\.(png|jpg|gif|svg)$/,
                use: [
                    { 
                        loader: 'file-loader',
                        options: {
                            name: '[name]-[hash:8].[ext]',
                            // 提取出来的图片放置在 image 目录下,后面的 / 不能省略
                            outputPath: 'image/'
                        }
                    }
                ]
            }
        ]
}
1.3 使用 url-loader

安装:

cnpm i -D url-loader

配置:

module.exports = {

    // ... 省略其他配置项
    
    // 模块:例如转换 es6, less, 图片转换等...
    module: {
        rules:[
        
            // ...省略其他配置项
            
            {
                test: /\.(png|jpg|gif|svg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 5120,
                            name: '[name]-[hash:8].[ext]',
                            outputPath: 'image/'
                        }
                    }
                ]
            }
        ]
    }
}

注意:url-loader 封装了 file-loader,使用时并不需要再安装 file-loader

limit 参数(字节/Byte):

当图片文件小于设定的值时,会把文件转换为 DataURL(Base64 格式)
当图片文件大于设定的值时,会默认调用 file-loader 进行处理,参数也会直接传给 file-loader,可通过 fallback 参数指定其他 loader 来处理

1.4 使用 html-withimg-loader

html-withimg-loader 处理 HTML 文件中 <img> 标签引用的图片

安装:

cnpm i -D html-withimg-loader

配置:

module.exports = {

    // ... 省略其他配置项
    
    // 模块:例如转换 es6, less, 图片转换等...
    module: {
        rules:[
        
            // ...省略其他配置项
            
            {
                test: /\.(htm|html)$/i,
                use: ['html-withimg-loader']
            }
        ]
    }
}

2、提取出来的 CSS 中图片路径不对

2.1 问题描述

当用 extract-text-webpack-plugin 插件提取 CSS 并指定存放目录时,生成的 CSS 中图片的引用路径并不正确
(注意:如果不指定 CSS 存放的目录,图片引用路径是正确的)

例如 extract-text-webpack-plugin 及图片处理配置如下:

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {

    // 入口文件的配置项
    entry: {
        index: './src/js/index.js'
    },
    // 出口文件的配置项
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/[name]-[chunkhash:8].js'
    },

    // ... 省略其他配置项
    
    module: {
        rules: [
            {
                // 用正则去匹配要用该 loader 转换的 CSS 文件
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    // 使用 css-loader 对 css 进行压缩
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                minimize: true
                            }
                        }
                    ]
                })
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                use: [
                    { 
                        loader: 'file-loader',
                        options: {
                            name: '[name]-[hash:8].[ext]',
                            // 提取出来的图片放置在 image 目录下,后面的 / 不能省略
                            outputPath: 'image/'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin({
          // 从 js 文件中提取出来的 css 文件的名称,前面可加存放路径
          filename: `css/[name]-[contenthash:8].css`,
        })
    ]
}

原始 main.css 内容及目录结构

.bg {
    background-image: url('../image/index/001.jpg');
}
|-- src
      |-- css
      |    |__ main.css
      |
      |-- image
            |--index
                 |__ 001.jpg

打包构建后生成的 index-5c5d3df7.css 内容及目录结构

.bg {
    background-image: url('image/001-de229472.jpg');
}
|-- dist
      |-- css
      |    |__ index-5c5d3df7.css
      |
      |-- image
            |__ 001-de229472.jpg

显然在 index-5c5d3df7.css 文件中是引用不到 001-de229472.jpg

如果我们不指定提取后 CSS 文件的存放目录,则默认生成在项目打包构建后的输出目录下

|-- dist
      |
      |-- image
      |    |__ 001-de229472.jpg
      |
      |__ index-5c5d3df7.css
      
<!-- index-5c5d3df7.css 内容不变-->

.bg {
    background-image: url('image/001-de229472.jpg');
}

这时 index-5c5d3df7.css 中对图片的引用地址是正确的

2.2 解决方法

配置 ExtractTextPlugin.extract() 中的 publicPath 选项,该选项要根据
new ExtractTextPlugin() 中是否对 CSS 设置了存放目录来配置

const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {

    // ... 省略其他配置项
    
    module: {
        rules: [
            {
                // 用正则去匹配要用该 loader 转换的 CSS 文件
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    // 使用 css-loader 对 css 进行压缩
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                minimize: true
                            }
                        }
                    ],
                    publicPath: '../'
                })
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin({
          // 从 js 文件中提取出来的 css 文件的名称,前面可加存放路径
          filename: `css/[name]-[contenthash:8].css`,
        })
    ]
}

为什么 publicPath 要用设置为 ../ ,因为 webpack 生成的 css ,默认位于项目打包构建后的输出目录下,这时图片的引用地址没有问题。

但是我们在 plugin 配置项 new ExtractTextPlugin({filename: 'css/[name]_[contenthash:8].css'}) 中,设置了生成的 CSS 文件存放在 css 目录下,相当于比原先的位置更深了一层,所以需要修正 CSS 文件中的引用路径往上再查找一层。

如果设置生成的 CSS 目录为 css/index/[name]_[contenthash:8].css,则 publicPath 要设置为 ../../,相当于需要往上再查找两层。

Webpack 学习第六步

1、优化输出的代码

目标:

  • 压缩输出的 JSCSSHTML
1.1 CSSHTML 的压缩

之前在我们的配置中,我们已经对 CSSHTML 进行了压缩
使用了 css-loaderhtml-webpack-plugin 插件,配置如下

module.exports = {

    // ... 省略其他配置项
    
    // 模块:例如转换 es6, less, 图片转换等...
    module: {
        rules:[
        
            // ...省略其他配置项
            
            {
                // 用正则去匹配要用该 loader 转换的 CSS 文件
                test: /\.css$/,
                use: ExtractTextPlugin.extract({    // 从 js 文件中提取 css 
                
                    // 使用 css-loader 对 css 进行压缩
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                minimize: true
                            }
                        }
                    ]
                })
            }
        ]
    }
    plugins: [
    
        // ...省略其他配置项
        
        new HtmlWebpackPlugin({
        
            // ...省略其他配置项
            
            // 对生成的 HTML 进行压缩配置
            minify: {
                removeComments : true,      //去掉注释
                collapseWhitespace : true   //去掉空行
            }
        })
    ]
}

其中 css-loader 内部使用的是 cssnano 来对 css 进行压缩,所以 cssnano 支持的压缩选项都可以在 css-loader 中进行配置,一般不进行配置,使用默认配置。

参考资料:

cssnano 官方文档
cssnano 更新日志

注意:
    这里使用的 css-loader 版本是 v0.28.8,其内部使用的 cssnano 版本是 v3.10.0,
    目前 cssnano 版本已经升级到了 v4.0.0,官方文档也是 v4.0.0 了,  
    如果要查看 v3.10.0 的信息应该对比 cssnano 的更新日志来看。
1.3 压缩 JS

使用 Webpack 内置的 uglifyjs-webpack-plugin 插件来压缩 JS,配置如下

参考资料(注意插件的版本号):

uglifyjs-webpack-plugin GitHub 地址
UglifyJS2 配置选项

const uglifyjs = require('uglifyjs-webpack-plugin');

module.exports = {

    // ... 省略其他配置项
    
    plugins: [
    
        // ...省略其他配置项
        
        new uglifyjs({
        
            // 相关配置参数与使用的 uglifyjs-webpack-plugin 版本有关
            
            // 生成 sourceMap,配合 devtool: 'sourceMap' 使用
            sourceMap: true,
            compress: {
                // 去掉 console 打印信息
                drop_console: true
            },
            beautify: false      // 格式化输出
        })
    ]
}
注意:
    我这里使用的 Webpack 3.6.0 中的 uglifyjs-webpack-plugin 版本是 v0.4.6,
    其中 uglifyjs-webpack-plugin 插件使用的是 UglifyJS2 版本是 v2.8.29
    配置 uglifyjs-webpack-plugin 参数时要查看对应版本的官方文档
    (一般去官方 GitHub 仓库查看对应的版本即可)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions