Webpack - 基本使用

Webpack

1、Webpack简介以及体验

1.1、Webpack简介

Webpack本质上是一个用于现代JavaScript应用程序的静态模块打包工具

静态模块:指的是编写代码过程中的,html,css,js,图片等固定内容的文件。

打包:把静态模块内容,压缩,整合,转译等(前端工程化)

  • 把less/sass转成css代码
  • 把ES6+降级成ES5
  • 支持多种模块标准语法

1.2、体验Webpack

  • 要求:封装utils包,校验手机号和验证码长度,在src/index.js中使用,使用Webpack打包

  • 步骤:

    1、新建项目文件夹TestWebpack,初始化包环境,得到package.json文件

    npm init -y
    

    2、新建src源代码文件夹(书写代码)包括utils/check.js封装用户名和密码长度函数,引入到src/index.js进行使用

    • src/utils/check.js

      //封装校验手机号长度和验证码长度的函数
      export const  checkPhone = phone => phone.length === 11
      export const  checkCode = code => code.length === 6
      
    • src/index.js

      //准备项目和源码
      import { checkCode, checkPhone } from "./utils/check.js"
      
      console.log(checkPhone('13999999999'))
      console.log(checkCode('123456789'));
      

    3、下载webpack webpack-cli到项目(版本独立)

    npm i webpack webpack-cli --save-dev
    

    注意:虽然 webpack 是全局软件包,封装的是命令工具,但是为了保证项目之间版本分别独立,所以这次比较特殊,下载到某个项目环境下,但是需要把 webpack 命令配置到 package.json 的 scripts 自定义命令,作为局部命令使用

    • package.json

      "scripts": {
      	"build": "webpack"
      }
      

    4、项目中运行工具命令,采用自定义命令的方式(局部命令)

    npm run build
    

    npm run 自定义命令名字

    注意:实际上在终端运行的是build右侧的具体命名

    5、自动产生dist分发文件夹(压缩和优化后,用于最终运行的代码)

2、修改Webpack打包入口和出口

Webpack配置:影响web pack打包过程和结果

步骤:

1、项目根目录,新建webpack.config.js配置文件

2、导出配置对象,配置入口,出口文件的路径

const path = require('path')

module.exports = {
  entry: path.resolve(__dirname, 'src/login/index.js'),
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: './login/index.js'  
  }
}

3、重新打包观察(只有和入口产生直接/间接的引入关系,才会被打包)

3、自动生成HTML文件

我们在打包js文件时,它不会生成响应的HTML文件,这里我们就需要使用到自动生成HTML文件的插件html-webpack-plugin在Webpack打包时生成html文件。

步骤:

1、下载html-webpack-plugin本地软件包

npm i html-webpack-plugin --save-dev

2、配置webpack.config.js让Webpack拥有插件功能

// ...
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/login.html', // 模板文件
      filename: './login/index.html' // 输出文件
    })
  ]
}

3、重新运行打包命令

npm run build

4、打包css代码

当然我们在打包时还需要打包css文件,但是Webpack默认只识别js和JSON文件内容,因此我们使用加载器,让Webpack识别更多类型的内容。

在打包css代码时只要是使用这两个加载器:

  • 加载器css-loader:解析css代码
  • 加载器style-loader:把解析后的css代码插入到DOM

步骤:

1、准备css文件代码引入到src/login.index.js中(压缩转译处理等)

import './index.css'
import 'bootstrap/dist/css/bootstrap.min.css' 

2、下载css-loader和style-loader本地软件包

npm i css-loader style-loader --save-dev

3、配置webpack.config.js让Webpack拥有该加载器功能

module.exports = {
  // ...
  module: { // 加载器
    rules: [ // 规则列表
      {
        test: /\.css$/i, // 匹配 .css 结尾的文件
        // 使用从后到前的加载器来解析 css 代码和插入到 DOM
        use: ['style-loader', 'css-loader'], 
      }
    ]
  }
};

4、运行打包查看打包效果

5、优化-提取css代码

我们用加载器的形式打包的css代码,我们可以发现它并没有生成css文件,而是整合到了js文件中,这样导致js文件体积变得很大,为解决这个问题我们就可以采用插件mini-css-extract-pligin插件提起css代码,注意不能和style-loader一起使用。

步骤:

1、下载mini-css-extract-plugin本地软件包

npm i mini-css-extract-plugin --save-devb

2、配置webpack.config.js让Webpack拥有该插件功能

  const MiniCssExtractPlugin = require('mini-css-extract-plugin')

  plugins: [
    new MiniCssExtractPlugin()
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },

3、运行打包查看打包效果

6、优化-压缩过程

我们使用Webpack主要是为了把所有的文件都进行打包压缩,但是css代码我们并没有压缩只是把它提取成为了一个单独的代码文件,为了压缩css代码我们就需要使用css-minimizer-webpack-plugin插件。

步骤:

1、下载mini-css-extract-plugin本地软件包

npm i css-minimizer-webpack-plugin --save-devb

2、配置webpack.config.js让Webpack拥有该插件功能

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

  optimization: {
    minimizer: [
      // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [new MiniCssExtractPlugin()],

3、运行打包查看打包效果

7、打包less代码

对于less代码我们也是使用加载器less-loader对less代码进行打包,less-loader需要配合less软件包使用。

步骤:

1、新建less代码(设置背景图)并引入到src/login/index.js中

2、下载less和less-loader本地软件包

npm i less less-loader --save-devb

3、配置webpack.config.js让Webpack拥有该插件功能

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

  optimization: {
    minimizer: [
      // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [new MiniCssExtractPlugin()],

4、运行打包查看打包效果

8、打包图片

由于Webpack只能识别js文件,所以我们的在开发中使用的图片也是需要打包,在Webpack5中内置了资源模块的打包,无需下载额外 loader 。

步骤:

1、配置 webpack.config.js 让 Webpack 拥有打包图片功能,占位符 【hash】对模块内容做算法计算,得到映射的数字字母组合的字符串,占位符 【ext】使用当前模块原本的占位符,例如:.png / .jpg 等字符串,占位符 【query】保留引入文件时代码中查询参数(只有 URL 下生效)。

2、注意:判断临界值默认为 8KB

大于 8KB 文件:发送一个单独的文件并导出 URL 地址

小于 8KB 文件:导出一个 data URI(base64字符串)

3、在 src/login/index.js 中给 img 标签添加 logo 图片

/**
 * 目标9:打包资源模块(图片处理)
 *  9.1 创建 img 标签并动态添加到页面,配置 webpack.config.js
 *  9.2 打包后观察效果和区别
 */
// 9.1 创建 img 标签并动态添加到页面,配置 webpack.config.js
// 注意:js 中引入本地图片资源要用 import 方式(如果是网络图片http地址,字符串可以直接写)
import imgObj from './assets/logo.png'
const theImg = document.createElement('img')
theImg.src = imgObj
document.querySelector('.login-wrap').appendChild(theImg)

4、配置 webpack.config.js 让 Webpack 拥有打包图片功能

// ...

module.exports = {
  // ...
  module: {
    rules: [
      // ...
      {
        test: /\.(png|jpg|jpeg|gif)$/i,
        type: 'asset',
        generator: {
          filename: 'assets/[hash][ext][query]'
        }
      }
    ]
  }
}

9、搭建开发环境

每次改动代码,都要重新打包,很麻烦,所以这里给项目集成 webpack-dev-server 开发服务器,主要作用是启动 Web 服务,打包输出源码在内存,并会自动检测代码变化热更新到网页。

步骤:

1、下载 webpack-dev-server 软件包到当前项目

npm i webpack-dev-server --save-dev

2、配置自定义命令,并设置打包的模式为开发模式

// ...

module.exports = {
  // ...
  mode: 'development'
}
"scripts": {
  // ...
  "dev": "webpack serve --mode=development"
},

3、使用 npm run dev 来启动开发服务器,访问提示的域名+端口号,在浏览器访问打包后的项目网页,修改代码后试试热更新效果

在 js / css 文件中修改代码保存后,会实时反馈到浏览器

10、打包模式

打包模式主要有两种模式,分别是开发模式和生产模式,主要是告知Webpack使用相应模式的内置优化。

模式名称模式名字特点场景
开发模式development调试代码,实时加载,模块热替换等本地开发
生产模式production压缩代码,资源优化,更轻量等打包上线

设置方式:

  • 在webpack.config.js配置文件设置mode选项
  • 在package.json命令行设置mode参数

命令行设置的优先级高于配置文件中的,推荐用命令行设置,推荐使用命令行方式。

  1. 如何设置影响 Webpack呢?

    • 方式1:在 webpack.config.js 配置文件设置 mode 选项

      // ...
      
      module.exports = {
        // ...
        mode: 'production'
      }
      
    • 方式2:在 package.json 命令行设置 mode 参数

      "scripts": {
        "build": "webpack --mode=production",
        "dev": "webpack serve --mode=development"
      },
      
  2. 体验:在 build 命令后 修改 mode 的值,打包输出观察打包后的 js 文件内容

11、打包模式的应用

在开发模式下用style-loader内嵌更快,在生产模式下提取css代码

方法:

  • webpack.config.js 配置导出函数,但是局限性大(只接受 2 种模式)
  • 借助 cross-env (跨平台通用)包命令,设置参数区分环境
  • 配置不同的 webpack.config.js (适用多种模式差异性较大情况)

步骤:

1、下载 cross-env 软件包到当前项目

npm i cross-env --save-dev

2、配置自定义命令,传入参数名和值(会绑定到 process.env 对象下)

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "build": "cross-env NODE_ENV=production webpack --mode=production",
  "dev": "cross-env NODE_ENV=development webpack serve --open --mode=development"
},

3、在 webpack.config.js 区分不同环境使用不同配置

module: {
  rules: [
    {
      test: /\.css$/i,
      // use: ['style-loader', "css-loader"],
      use: [process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader, "css-loader"]
    },
    {
      test: /\.less$/i,
      use: [
        // compiles Less to CSS
        process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
        'css-loader',
        'less-loader',
      ],
    }
  ],
},

4、重新打包观察两种配置区别

12、前端-注入环境变量

cross-env 设置的只在 Node.js 环境生效,前端代码无法访问 process.env.NODE_ENV。为解决这个问题我们可以使用 Webpack 内置的 DefinePlugin 插件,在编译时,将前端代码中匹配的变量名,替换为值或表达式,配置 webpack.config.js 中给前端注入环境变量。

// ...
const webpack = require('webpack')

module.exports = {
  // ...
  plugins: [
    // ...
    new webpack.DefinePlugin({
      // key 是注入到打包后的前端 JS 代码中作为全局变量
      // value 是变量对应的值(在 corss-env 注入在 node.js 中的环境变量字符串)
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    })
  ]
}

13、开发环境调错-source map

代码被压缩和整合之后,我们无法正确定位源代码的位置(行数和列数),面对代码的报错我们找不到问题的出处,为解决这个问题,webpack推出了source map这个功能,它可以准确追踪error和warning在原始代码的位置。只需要在webpack.config.js中配置devtool选项。

//...

module.exports = {
  //...
  devtool: 'inline-source-map'
}

inline-source-map 选项:把源码的位置信息一起打包在 JS 文件内

注意:source map 适用于开发环境,不要在生产环境使用(防止被轻易查看源码位置)

14、解析别名

我们在引入模块时,模块的路径或者名称存在共同部分,引入模块就有大量代码重复,这时候我们就可以使用接卸别名,把公共部分提取出来,用指定的别名来代替共同部分,让模块的引用变得更加简单。

演示:

1、原来的引用模块路径

import { checkPhone, checkCode } from '../src/utils/check.js'

2、在webpack.config.js中配置解析别名

//...
const config = {
	//...
	resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  }
}

3、配置以后我们引入模块

import { checkPhone, checkCode } from '@utils/check.js'

15、优化-CND使用

CDN是指内容分发网络,指的是一组分布在各个地区的服务器,它的作用是把静态资源文件/第三方库放在CDN网络中各个服务器中,供用户就近请求获取,它能够减轻自己服务器请求压力,就近请求物理延迟,配套缓存策略。

步骤:

1、在html中引入第三方库的CDN地址并用模板语法判断

<% if(htmlWebpackPlugin.options.useCdn){ %>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<% } %>

2、配置 webpack.config.js 中 externals 外部扩展选项(防止某些 import 的包被打包)

// 生产环境下使用相关配置
if (process.env.NODE_ENV === 'production') {
  // 外部扩展(让 webpack 防止 import 的包被打包进来)
  config.externals = {
    // key:import from 语句后面的字符串
    // value:留在原地的全局变量(最好和 cdn 在全局暴露的变量一致)
    'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
    'axios': 'axios'
  }
}
// ...
const config = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      // ...
      // 自定义属性,在 html 模板中 <%=htmlWebpackPlugin.options.useCdn%> 访问使用
      useCdn: process.env.NODE_ENV === 'production'
    })
  ]
}

16、多页面打包

单页面是指单个html文件,切换DOM的方式实现不同业务逻辑展示。

多页面是指多个html文件,切换页面实现不同业务逻辑展示。

配置 webpack.config.js 多入口和多页面的设置

// ...
const config = {
  entry: {
    '模块名1': path.resolve(__dirname, 'src/入口1.js'),
    '模块名2': path.resolve(__dirname, 'src/入口2.js'),
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: './[name]/index.js'  
  }
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/页面2.html', // 模板文件
      filename: './路径/index.html', // 输出文件
      chunks: ['模块名2']
    })
    new HtmlWebpackPlugin({
      template: './public/页面2.html', // 模板文件
      filename: './路径/index.html', // 输出文件
      chunks: ['模块名2']
    })
  ]
}

17、优化-分隔公共代码

当页面数量比较多的时候,一定会存在公共代码,分隔公共代码主要是为了将页面中的公共部分单独分隔出来,从而进一步压缩代码。

配置 webpack.config.js 的 splitChunks 分割功能

// ...
const config = {
  // ...
  optimization: {
    // ...
    splitChunks: {
      chunks: 'all', // 所有模块动态非动态移入的都分割分析
      cacheGroups: { // 分隔组
        commons: { // 抽取公共模块
          minSize: 0, // 抽取的chunk最小大小字节
          minChunks: 2, // 最小引用数
          reuseExistingChunk: true, // 当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用
          name(module, chunks, cacheGroupKey) { // 分离出模块文件名
            const allChunksNames = chunks.map((item) => item.name).join('~') // 模块名1~模块名2
            return `./js/${allChunksNames}` // 输出到 dist 目录下位置
          }
        }
      }
    }
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值