webpack通俗易懂(二)

webpack通俗易懂(二)

  • 1,自动引入打包后的资源
  • 2,搭建开发环境
  • 3, 资源模块
  • 4,管理资源

1,自动引入打包后的资源

通过webpack的一些插件可以实现自动引入资源

1.1,插件

插件 是 webpack 的核心功能。Webpack 提供很多开箱即用的插件

插件可以用于执行一些特定的任务,包括: 打包优化,资源管理,注入环境变量等。
Webpack 自身也是构建于我们在 webpack 配置中用到的相同的插件系统上!

想要使用一个插件,只需要 require() 它,然后把它添加到 plugins 数组中。 多数插件可以通过选项(option)自定义。也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例

1.2,使用 HtmlWebpackPlugin

首先安装插件:

npm install --save-dev html-webpack-plugin

并且修改 webpack.config.js 文件:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = { // 定义模块
  entry: './src/index.js', // 入口
  output: {  // 出口
    filename: 'test.js', // 文件名
    path: path.resolve(__dirname, './dist') // 路径。 path值一定设置成绝对路径
  },
  mode: 'none',
  plugins: [ // 可以配置多个插件
    new HtmlWebpackPlugin()
  ]
}

执行,npx webpack,会创建dist文件夹,dist -> index.html 和 test.js

webpack通俗易懂(二)_第1张图片
运行 dist 下的index.html,也可以打印出:Hello World~

那么打包后,我们发现这个 dist/index.html 似乎与先前的 index.html 并没有关 系,HtmlWebpackPlugin 会默认生成它自己的 index.html 文件,并且所有的 test(test.js) 会自动添加到 html 中。

能否基于原有的 index.html 文件打包生成新的 index.html 呢?可以通过阅读 HtmlWebpackPlugin 插件提供的全部的功能和选项来找到答案。
首先删除 index.html 手工引入的 js 文件:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = { // 定义模块
  entry: './src/index.js', // 入口
  output: {  // 出口
    filename: 'test.js', // 文件名
    path: path.resolve(__dirname, './dist') // 路径。 path值一定设置成绝对路径
  },
  mode: 'none',
  plugins: [ // 可以配置多个插件
    new HtmlWebpackPlugin({ 实例化 html-webpack-plugin 插件
      template: './index.html', // 打包生成的文件的模板
      filename: 'app.html', // 打包生成的文件名称。默认为index.html
      inject: 'body' // // 设置所有资源文件注入模板的位置。可以设置的值
true|'head'|'body'|false,默认值为 true
    })
  ]
}


这时候,打包好之后的目录如下:

webpack通俗易懂(二)_第2张图片
既然有了app.html,那么怎么把之前打包好的index.html 文件删除呢?或者删除之前打包的js或者其他的资源呢?
这时候只需要在webpack.config.js文件的output里添加clean: true即可:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = { // 定义模块
  entry: './src/index.js', // 入口
  output: {  // 出口
    filename: 'test.js', // 文件名
    path: path.resolve(__dirname, './dist'), // 路径。 path值一定设置成绝对路径
    clean: true // 打包前清理 dist 文件夹
  },
  mode: 'none',
  plugins: [ // 可以配置多个插件
    new HtmlWebpackPlugin({ 实例化 html-webpack-plugin 插件
      template: './index.html',// 打包生成的文件的模板
      filename: 'app.html', // 打包生成的文件名称。默认为index.html
      inject: 'body' // 设置所有资源文件注入模板的位置。可以设置的值
true|'head'|'body'|false,默认值为 true
    })
  ]
}

每次我们访问打包好的html文件,为了提高开发效率,我们可以我们搭建一个开发环境,这样就解决了用户每次复制文件地址去访问的问题了。

2,搭建开发环境

以上我们只能通过复制 dist/index.html 完整的物理路径到浏览器地址栏里访
问页面。我们可以通过设置一个开发环境,使我们的开发体验变得更轻松一些

2.1,mode 选项

// webpack.config.js
module.exports = {
  mode: 'development'  // 开发模式
}

再次执行npx webpack, 查看打包之后生成的test.js:

webpack通俗易懂(二)_第3张图片
上图是打包后的test.js, eval(…),怎么才能打包成我们可以看懂的test.js文件呢?

2.2,使用 source map

接着文章webpack(一)中的实例,将hello.js中的console.log改写为cosole.log,
再次npx webpack编译,后在浏览器打开打包好后的index.html:


点击上图给出的引导hello.js报错,点开后发现并不是源代码文件:


这时候我们需要配置 devtool: inline-source-map 选项:

// webpack.config.js
module.exports = {
// 在开发模式下追踪代码
  devtool: 'inline-source-map',
}

再次编译后,就可以追踪到错误的源代码了:

webpack通俗易懂(二)_第4张图片

2.3,使用 watch mode(观察模式)

在每次编译代码时,我们都要手动运行 npx webpack 会很麻烦,
我们可以在 webpack 启动时添加 “watch” 参数。如果其中一个文件被更新,代码将被重新编译,所以不必再去手动运行整个构建

npx webpack --watch

缺点是,为了看到修改后的实际效果,我们需要刷新浏览器。如果能够自动刷新浏览器就更好了,因此接下来我们会通过 webpack-dev-server 实现此功能

2.4,使用 webpack-dev-server

webpack-dev-server 为你提供了一个基本的 web server,并且具有 live
reloading(实时重新加载) 功能。先安装:

npm install --save-dev webpack-dev-server -D // -D 本地的开发环境

并修改配置文件:

module.exports = {
  // dev-server
  devServer: {
    static: './dist' // 此配置告知 webpack-dev-server ,将 dist 目录下的文件作为 web 服务的根目录
  }
}

然后运行npx webpack-dev-server:

webpack通俗易懂(二)_第5张图片

打开http://localhost:8080/也可以访问到:

完全不影响。

3, 资源模块

现在我们尝试混合
一些其他资源,比如 images,看看 webpack 如何处理。

在 webpack 出现之前,前端开发人员会使用 grunt 和 gulp 等工具来处理资源,并
将它们从 /src 文件夹移动到 /dist 或 /build 目录中。webpack 最出色的功能
之一就是,除了引入 JavaScript,还可以内置的资源模块 Asset Modules 引入任何
其他类型的文件。

资源模块(asset module)是一种模块类型,允许我们应用Webpack来打包其他资
源文件(如字体,图标等)
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些loader:

  • asset/resource 发送一个单独的文件并导出 URL
  • asset/inline 导出一个资源的 data URI
  • asset/source 导出资源的源代码
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择

3.1, resource 资源

修改 webpack.config.js 配置:

// 配置资源文件 
module: {
  rules: [{
    test: /\.png/,
    type: 'asset/resource'
  }]
},
// index.js
import imgSrc from './imgs/WechatIMG770.png'

const img = document.createElement('img')
img.src = imgSrc
img.style.cssText = 'width: 500px;height: auto'
document.body.appendChild(img)

执行npx webpack-dev-server, 浏览器显示:

webpack通俗易懂(二)_第6张图片

3.2, 自定义输入文件名:

  • 方法一:
    • 默认情况下,asset/resource 模块以 [contenthash][ext][query] 文件名
      发送到输出目录。
    • 可以通过在 webpack 配置中设置 output.assetModuleFilename 来修改此模版字符串
output: {
   assetModuleFilename: 'images/[contenthash][ext][query]'
},
  • 方法二:
    • 将某些资源发送到指定目录,修改配置
rules: [{
  test: /\.png/,
  type: 'asset/resource',
  generator: { // 优先级高于 assetModuleFilename 
    filename: 'images/[contenthash][ext][query]'
  }
}]

3.3, inline 资源

修改 webpack.config.js 配置:

// 配置资源文件 
module: {
  [
    {
      type: 'asset/inline'
    }
  ], 
}
// index.js
import svgSrc from './imgs/success.svg'

const img1 = document.createElement('img')
img1.style.cssText = 'width: 50px;height: 50px'
img1.src = svgSrc
document.body.appendChild(img1)

执行npx webpack-dev-server, 浏览器显示:

webpack通俗易懂(二)_第7张图片

3.4, source 资源

source资源,导出资源的源代码。修改配置文件:

module: {
  rules: [
    {
      test: /\.txt/,
      type: 'asset/source'
    }
  ]
}
// index.js
import txt from './test.txt'

const txtTemp = document.createElement('div')
txtTemp.style.cssText = 'width: 100px;height: 100px; background-color: #efefef'
txtTemp.textContent = 'Hello webpack'
document.body.appendChild(txtTemp)

执行npx webpack-dev-server, 浏览器显示:
webpack通俗易懂(二)_第8张图片

3.5, 通用资源类型asset

在导出一个 data URI 和发送一个单独的文件之间自动选择。
修改配置文件:

module: {
  rules: [
    {
      test: /\.jpg/,
      type: 'asset'
    }
  ]
}

webpack 将按照默认条件,自动地在 resource 和 inline 之间进行选择: 小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型

import imgSrc from './imgs/b3cae8dbb98590fe74b1b9c2255410b3.jpg' // 这张图大小 291kb

const img2 = document.createElement('img')
img2.style.cssText = 'width: 500px;height: auto'
img2.src = imgSrc
document.body.appendChild(img2)

执行后浏览器显示,会选择用resource资源模块:

webpack通俗易懂(二)_第9张图片

可以通过在 webpack 配置的 module rule 层级中,设置Rule.parser.dataUrlCondition.maxSize 选项来修改此条件:

rules: [
  {
    test: /\.jpg/,
    type: 'asset',
    parser: {
      dataUrlCondition: {
        maxSize: 20 * 1024 * 1024  // 因为
      }
    }
  } 
]

执行后,浏览器显示改为inline资源模块:

webpack通俗易懂(二)_第10张图片

4,管理资源

除了资源模块,我们还可以通过 loader 引入其他类型的文件

4.1, loader

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带的能力。 loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。

在 webpack 的配置中,loader 有两个属性:

    1. test 属性,识别出哪些文件会被转换。
    1. use 属性,定义出在进行转换时,应该使用哪个 loader。
module: {
  rules: [
    {
      test: /\.txt$/, 
      use: 'raw-loader'
    }
  ],
},

以上配置 module 对象定义了 rules 属性,里面包含两个必须属性: test 和 use,这告诉 webpack 编译器(compiler) 如下信息:
“嘿,webpack 编译器,当你碰到「在 require() / import 语句中被解析为 ‘.txt’ 的路径」时,在你对它打包之前,先 use(使用) raw-loader 转换一下”

4.2, 加载CSS

为了在 JavaScript 模块中 import 一个 CSS 文件,需要安装 style-loader 和 css-loader,并在 module 配置中添加这些 loader:

npm install --save-dev style-loader css-loader

修改配置文件:

module: {
  rules: [
    {
      test: /\.css$/i,
      use: ['style-loader', 'css-loader']
    }
  ]
}
// style.css
.content {
  background-color: rgb(235, 245, 222)
}
// index.js
import './style.css'
document.body.classList.add('content')

webpack通俗易懂(二)_第11张图片
现有的 loader 可以支持任何我们可以想到的 CSS 风格 - sass 和 less 等。安装less- loader:

npm install less less-loader --save-dev

修改配置文件:

module: {
  rules: [
    {
      test: /\.less$/i,
      use: ['style-loader', 'css-loader', 'less-loader']
    }
  ]
}
// style.less
@color: rgb(245, 238, 222);
.content {
  background-color: @color;
}

// index.js
import './style.less'
document.body.classList.add('content')

webpack通俗易懂(二)_第12张图片

4.3, 抽离和压缩CSS

我们也可以进行压缩CSS,以便在生产环境中节省加载时间,同时还可以将CSS文件抽离成一个单独的文件。实现这个功能,需要mini-css-extract-plugin插件, 安装插件:

npm install mini-css-extract-plugin --save-dev

修改配置文件:

const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = { // 定义模块
  plugins: [ // 可以配置多个插件
    new MiniCssExtractPlugin()
  ],
  // 资源
  module: {
    rules: [
      {
        test: /\.(css|less)$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
      }
    ]
  }
}

执行编译npx webpack

webpack通俗易懂(二)_第13张图片

单独的mini-css-extract-plugin插件不能将这些css加载到页面中,html-webpack-plugin帮我们自动生成link标签或者在创建index.html文件时使用link标签

webpack通俗易懂(二)_第14张图片

以上可以看出,main.css文件被打包抽离到 dist 根目录下,我们可以配置将其打包到一个单独的文件夹里:

plugins: [
  new MiniCssExtractPlugin({
    filename: 'styles/[contenthash].css'
  })
]

npx webpack编译后:
webpack通俗易懂(二)_第15张图片
app.html文件引用的路径同样更新了:

打开 .css 文件:

webpack通俗易懂(二)_第16张图片
发现文件并没有压缩和优化,为了压缩输出的文件,可以使用 css-minimizer-webpack-plugin 插件,安装该插件:

npm install --save-dev css-minimizer-webpack-plugin

修改配置文件:

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

mode: 'production',
// 优化配置
optimization: {
  minimizer: [
    new CssMinimizerPlugin()
  ]
}

npx webpack编译:

webpack通俗易懂(二)_第17张图片

4.4,加载 images 图像

当我们正在下载 CSS 的时候,但是像 background 和 icon 这样的图像,要如何处理呢?在 webpack 5 中,可以使用内置的 Asset Modules,我们可以轻松地将这些内容混入我们的系统中。在 css 文件里也可以直接引用文件,修改 style.css 和入口 index.js:

修改配置文件:

mode: 'development',
// style.less
.div-bg {
  background-image: url(imgs/01.jpg);
}

// index.js
const txtTemp = document.createElement('div')
txtTemp.textContent = 'Hello webpack'
txtTemp.classList.add('div-bg')
document.body.appendChild(txtTemp)

webpack通俗易懂(二)_第18张图片

你可能感兴趣的:(webpack,webpack,前端,javascript)