资讯专栏INFORMATION COLUMN

24 个实例入门并掌握「Webpack4」(二)

hlcc / 1376人阅读

摘要:代码如下所示按照正常使用习惯,操作来实现样式的添加和卸载,是一贯技术手段。将帮助我们进行操作。

继 24 个实例入门并掌握「Webpack4」(一) 后续:

JS Tree Shaking

CSS Tree Shaking

图片处理汇总

字体文件处理

处理第三方 js 库

开发模式与 webpack-dev-server

开发模式和生产模式・实战

打包自定义函数库

九、JS Tree Shaking

demo9 源码地址

什么是 Tree Shaking?

字面意思是摇树,项目中没有使用的代码会在打包的时候丢掉。JS 的 Tree Shaking 依赖的是 ES6 的模块系统(比如:import 和 export)

项目目录如下:

在 util.js 文件中写入测试代码

// util.js
export function a() {
  return "this is function "a""
}

export function b() {
  return "this is function "b""
}

export function c() {
  return "this is function "c""
}

在 app.js 中引用 util.js 的 function a() 函数,按需引入

// app.js
import { a } from "./vendor/util"
console.log(a())

命令行运行 webpack 打包后,打开打包后生成的 /dist/app.bundle.js 文件。查找我们 a() 函数输出的字符串,如下图所示:

如果将查找内容换成 this is function "c" 或者 this is function "b", 并没有相关查找结果。说明 JS Tree Shaking 成功。

1. 如何处理第三方 JS 库?

对于经常使用的第三方库(例如 jQuery、lodash 等等),如何实现 Tree Shaking ?

下面以 lodash.js 为例,进行介绍。

安装 lodash.js : npm install lodash --save

在 app.js 中引用 lodash.js 的一个函数:

// app.js
import { chunk } from "lodash"
console.log(chunk([1, 2, 3], 2))

命令行打包。如下图所示,打包后大小是 70kb。显然,只引用了一个函数,不应该这么大。并没有进行 Tree Shaking。

开头讲过,js tree shaking 利用的是 ES 的模块系统。而 lodash.js 使用的是 CommonJS 而不是ES6 的写法。所以,安装对应的模块系统即可。

安装 lodash.js 的 ES 写法的版本:npm install lodash-es --save

修改一下 app.js:

// app.js
import { chunk } from "lodash-es"
console.log(chunk([1, 2, 3], 2))

再次打包,打包结果只有 3.5KB(如下图所示)。显然,tree shaking 成功。

在一些对加载速度敏感的项目中使用第三方库,请注意库的写法是否符合 ES 模板系统规范,以方便 webpack 进行 tree shaking。
十、CSS Tree Shaking

demo10 源码地址

CSS Tree Shaking 并不像 JS Tree Shaking 那样方便理解,首先要模拟一个真实的项目环境,来体现 CSS 的 Tree Shaking 的配置和效果。

此章节源码基于第八节处理 CSS 项目上做修改

我们首先编写 /src/css/base.css 样式文件,在文件中,我们编写了 3 个样式类。但在代码中,我们只会使用 .box 和 .box--big 这两个类。代码如下所示:

/* base.css */
html {
  background: red;
}

.box {
  height: 200px;
  width: 200px;
  border-radius: 3px;
  background: green;
}

.box--big {
  height: 300px;
  width: 300px;
  border-radius: 5px;
  background: red;
}

.box-small {
  height: 100px;
  width: 100px;
  border-radius: 2px;
  background: yellow;
}

按照正常使用习惯,DOM 操作来实现样式的添加和卸载,是一贯技术手段。所以,入口文件 /src/app.js 中创建了一个

标签,并且将它的类设为 .box

// app.js
import base from "./css/base.css"

// 给 app 标签再加一个 div 并且类名为 box
var app = document.getElementById("app")
var div = document.createElement("div")
div.className = "box"
app.appendChild(div)

最后,为了让环境更接近实际环境,我们在 index.html 的一个标签,也引用了定义好的 box-big 样式类。



  
    
    
    
    CSS Tree Shaking
  

  
    

PurifyCSS将帮助我们进行 CSS Tree Shaking 操作。为了能准确指明要进行 Tree Shaking 的 CSS 文件,还有 glob-all (另一个第三方库)。

glob-all 的作用就是帮助 PurifyCSS 进行路径处理,定位要做 Tree Shaking 的路径文件。

安装依赖:

npm i glob-all purify-css purifycss-webpack --save-dev

更改配置文件:

const path = require("path")

const CleanWebpackPlugin = require("clean-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")

const MiniCssExtractPlugin = require("mini-css-extract-plugin") // 将 css 多带带打包成文件

const PurifyCSS = require("purifycss-webpack")
const glob = require("glob-all")

module.exports = {
  entry: {
    app: "./src/app.js"
  },
  output: {
    publicPath: "./", // js 引用的路径或者 CDN 地址
    path: path.resolve(__dirname, "dist"), // 打包文件的输出目录
    filename: "[name].bundle.js", // 代码打包后的文件名
    chunkFilename: "[name].js" // 代码拆分后的文件名
  },
  module: {
    rules: [
      {
        test: /.css$/, // 针对 .scss 或者 .css 后缀的文件设置 loader
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          "css-loader"
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      // 打包输出HTML
      title: "自动生成 HTML",
      minify: {
        // 压缩 HTML 文件
        removeComments: true, // 移除 HTML 中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true // 压缩内联 css
      },
      filename: "index.html", // 生成后的文件名
      template: "index.html", // 根据此模版生成 HTML 文件
      chunks: ["app"] // entry中的 app 入口才会被打包
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    }),
    // 清除无用 css
    new PurifyCSS({
      paths: glob.sync([
        // 要做 CSS Tree Shaking 的路径文件
        path.resolve(__dirname, "./*.html"), // 请注意,我们同样需要对 html 文件进行 tree shaking
        path.resolve(__dirname, "./src/*.js")
      ])
    })
  ]
}

打包完查看 dist/app.css 文件

在 index.html 和 src/app.js 中引用的样式都被打包了,而没有被使用的样式类–box-small,没有被打包进去

十一、图片处理汇总

demo11 源码地址

目录结构:

webpack4 中的图片常用的基础操作:

图片处理和 Base64 编码

图片压缩

合成雪碧图

(一) 准备工作

如项目代码目录展示的那样,除了常见的 app.js 作为入口文件,我们将用到的 3 张图片放在 /src/assets/imgs/ 目录下,并在样式文件 base.css 中引用这些图片。

剩下的内容交给 webpack 打包处理即可。样式文件和入口 app.js 文件的代码分别如下所示:

/* base.css */
*,
body {
  margin: 0;
  padding: 0;
}
.box {
  height: 400px;
  width: 400px;
  border: 5px solid #000;
  color: #000;
}
.box div {
  width: 100px;
  height: 100px;
  float: left;
}
.box .ani1 {
  background: url("./../assets/imgs/1.jpg") no-repeat;
}
.box .ani2 {
  background: url("./../assets/imgs/2.png") no-repeat;
}
.box .ani3 {
  background: url("./../assets/imgs/3.png") no-repeat;
}

app.js

import "./css/base.css"

安装依赖:

npm install url-loader file-loader --save-dev
(二) 图片处理和 base64 编码

webpack.config.js 中的 module.rules 选项中进行配置,以实现让 loader 识别图片后缀名,并且进行指定的处理操作。

module.exports = {
  module: {
    rules: [
      {
        test: /.(png|jpg|jpeg|gif)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              name: "[name]-[hash:5].min.[ext]",
              outputPath: "images/", //输出到 images 文件夹
              limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
            }
          }
        ]
      }
    ]
  }
}

完整的配置文件

const path = require("path")

const CleanWebpackPlugin = require("clean-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")

const MiniCssExtractPlugin = require("mini-css-extract-plugin") // 将 css 多带带打包成文件

module.exports = {
  entry: {
    app: "./src/app.js"
  },
  output: {
    publicPath: "./", // js 引用的路径或者 CDN 地址
    path: path.resolve(__dirname, "dist"), // 打包文件的输出目录
    filename: "[name].bundle.js", // 代码打包后的文件名
    chunkFilename: "[name].js" // 代码拆分后的文件名
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          "css-loader"
        ]
      },
      {
        test: /.(png|jpg|jpeg|gif)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              name: "[name]-[hash:5].min.[ext]",
              outputPath: "images/", //输出到 images 文件夹
              limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      // 打包输出HTML
      title: "自动生成 HTML",
      minify: {
        // 压缩 HTML 文件
        removeComments: true, // 移除 HTML 中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true // 压缩内联 css
      },
      filename: "index.html", // 生成后的文件名
      template: "index.html", // 根据此模版生成 HTML 文件
      chunks: ["app"] // entry中的 app 入口才会被打包
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ]
}

打包项目,查看打包结果,并在浏览器中打开 index.html 文件

可以看到除了 1.jpg,另外两张图片已经被打包成 base64 格式,在 app.css 文件中

1.jpg 这个文件超过我们在 url-loader 选项中设置的 limit 值,所以被多带带打包

这就是利用了 file-loader 的能力,如果在 url-loader 中设置了 limit 的值,却没有安装 file-loader 依赖,会怎么样?来试试看,首先卸载 file-loader 依赖npm uninstall file-loader,再运行打包命令,npm run build

如果图片较多,会发很多 http 请求,会降低页面性能。

url-loader 会将引入的图片编码,转为 base64 字符串。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了,节省了图片请求。

但是,如果图片较大,编码会消耗性能。因此 url-loader 提供了一个 limit 参数,小于 limit 字节的文件会被转为 base64,大于 limit 的使用 file-loader 进行处理,多带带打包。

url-loader 依赖 file-loader,url-loader 可以看作是增强版的 file-loader

(三) 图片压缩

图片压缩需要使用 img-loader 插件,除此之外,针对不同的图片类型,还要引用不同的插件。比如,我们项目中使用的是 png 图片,因此,需要引入 imagemin-pngquant,并且指定压缩率。压缩 jpg/jpeg 图片为 imagemin-mozjpeg 插件

这里有个 bug,可以先不急着操作,先把这一小节看完,再决定!!

安装依赖

npm i img-loader imagemin imagemin-pngquant imagemin-mozjpeg --save-dev

在之前的配置上更改:

{
  test: /.(png|jpg|jpeg|gif)$/,
  use: [
    {
      loader: "url-loader",
      options: {
        name: "[name]-[hash:5].min.[ext]",
        outputPath: "images/", // 输出到 images 文件夹
        limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
      }
    }
  ]
}

更改为:

{
  test: /.(png|jpg|jpeg|gif)$/,
  use: [
    {
      loader: "url-loader",
      options: {
        name: "[name]-[hash:5].min.[ext]",
        limit: 1000, // size <= 1KB
        outputPath: "images/"
      }
    },
    // img-loader for zip img
    {
      loader: "img-loader",
      options: {
        plugins: [
          require("imagemin-pngquant")({
            quality: "80" // the quality of zip
          }),
          require("imagemin-mozjpeg")({
            quality: "80"
          })
        ]
      }
    }
  ]
}

打包结果:

原因在 png 图片上,jpg 图片可以压缩,但是去 imagemin-pngquant github 上也没发现有人提出类似 issue ,百度、google 找了半天,还是没发现怎么解决

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/110208.html

相关文章

  • 24 实例入门掌握Webpack4」(一)

    摘要:前言此项目总共小节,目录搭建项目并打包文件生产和开发模式覆盖默认用转译自动生成文件处理文件图片处理汇总处理第三方库开发模式与开发模式和生产模式实战打包自定义函数库配置配置配置使用加快打包速度多页面打包配置编写编写编写前节基于渐进式教程为 前言 此项目总共 24 小节,目录: 搭建项目并打包 JS 文件 生产和开发模式 覆盖默认 entry/output 用 Babel 7 转译 ES...

    Tonny 评论0 收藏0
  • 24 实例入门掌握Webpack4」(三)

    摘要:继个实例入门并掌握二后续配置配置配置使用加快打包速度多页面打包配置编写编写编写十七配置源码地址本节使用的代码为基础我们来模拟平时开发中,将打包完的代码防止到服务器上的操作,首先打包代码然后安装一个插件在中配置一个命令运 继 24 个实例入门并掌握「Webpack4」(二) 后续: PWA 配置 TypeScript 配置 Eslint 配置 使用 DLLPlugin 加快打包速度 多...

    mindwind 评论0 收藏0
  • 【Cute-Webpack】Webpack4 入门手册(共 18 章)

    摘要:介绍背景最近和部门老大,一起在研究团队前端新手村的建设,目的在于帮助新人快速了解和融入公司团队,帮助零基础新人学习和入门前端开发并且达到公司业务开发水平。 showImg(https://segmentfault.com/img/remote/1460000020063710?w=1300&h=646); 介绍 1. 背景 最近和部门老大,一起在研究团队【EFT - 前端新手村】的建设...

    AlanKeene 评论0 收藏0
  • 关于Vue2一些值得推荐的文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    sutaking 评论0 收藏0

发表评论

0条评论

hlcc

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<