Webpack打包基础及原理

Webpack模块化打包工具出现的意义

  • 新特性打包编译: ESM有环境兼容问题,需要打包工具将开发阶段的一些文件在生产阶段直接编译成兼容绝大多数环境的代码。
  • 模块化JS打包: 将模块文件打包到bundle.js文件中,解决了浏览器中频繁对模块文件发出请求的问题。
  • 支持不同种类型的资源模块

Webpack快速上手

  1. 初始化生成package.json文件
    webpack本质是npm的一个工具模块,通过yarn init初始化的方式生成配置文件
yarn init --yes
  1. 安装webpack核心模块及webpack-cli模块
yarn add webpack webpack-cli --dev

安装完成之后,对应的webpack和webpack-cli文件在modules的bin目录中。
3. yarn webpack运行打包
自动通过src目录下的index.js开始打包。打包文件默认在dist的main.js。

yarn webpack

Webpack自定义配置文件

在根目录下新建webpack.config.js文件

  • entry 入口
  • output出口
  • loader用于对模块的源代码进行转换,转换为js代码

工作模式

通过mode指定打包模式(可以在配置文件中直接设置mode值,也可以打包命令中通过–mode 指定):

  • development

会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。

  • production

会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.

loader

三种使用方式:

  • **配置:**在webpack.config.js文件中指定loader
 module: {
    rules: [
      {
        test: /\.css$/,
        //多个loader时,执行顺序为从下到上
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
  • **内联:**在每个import语句中显示指定loader
    使用!将资源中的loader分开。?用于传递查询参数
import Styles from 'style-loader!css-loader?modules!./styles.css';
  • **CLI:**在shell命令中指定
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

文件资源加载器

file-loader将资源文件加载打包到指定文件中,一般默认在dist目录中。而加载解析时默认从根目录取资源。因此需要通过publicPath设置打包输入文件路径。打包文件会在资源读取时在前面拼接上配置的路径(因为时拼接的路径,所以最后的/不可省略)。

output:{
	publicPath:'dist/'
}

除了file-loader打包加载资源,通过路径使用的方式。还有URL加载器,直接将文件转换为data文件形式,放在打包文件中。但有些文件转换为data文件形式后很大,所以一般采用以下处理方式:

  • 小文件使用Data URLs,减少请求次数
  • 大文件单独提取存放,提高加载速度
    一般loader都有一些额外的配置来处理需要对应loader处理的文件。比如url-loader中limit:
{
	test:/.png$/,
	use:{
		loader:'url-loader',
		options:{
			limit:10 * 1024 //10kb以下的文件才会被url-loader处理为data文件形式
		}
	}
}

常用loader大致分类

  • 编译转换类:css-loader、babel-loader
  • 文件操作类:file-loader
  • 代码检查类:eslint-loader

babel用于将ES6编译成ES5处理新特性。通常需要一起安装依赖的核心模块@babel/code @babel/preset-env

webpack加载资源的方式

  • 遵循ES Modules标准的import声明
  • 遵循CommonJs标准的require函数
  • 遵循AMD标准的define函数和require函数
  • 样式代码中的@import指令和url函数
  • HTML代码中图片标签的src属性

webpack核心工作原理

  1. 通过配置文件找到打包文件入口,一般都是一个js文件
  2. 在入口文件中通过import或者require关键词推断解析出依赖的模块
  3. 分别解析每个模块对应的依赖,形成体现整个项目依赖关系的依赖树。
  4. 递归依赖树,找到每个节点对应的资源文件
  5. 通过rules中的配置找到每个资源文件对应的loader,对资源进行加载
  6. 将通过loader加载的结果放到打包结果bundel.js中
    在这里插入图片描述

webpack插件机制

webpack插件是一个具有apply属性的JavaScript对象。apply属性会被webpack compiler调用,并且compiler对象可在整个编译生命周期访问。

常用的插件:
clean-webpack-plugin自动清除输入目录插件。
html-webpack-plugin通过webpack输出HTML文件。

**copy-webpack-plugin复制文件。**接收一个数组参数,数组中为需要拷贝的文件目录

html-webpack-plugin可配置title、meta等参数。还可以通过模板文件的形式生成html文件。

html-webpack-plugin是将由依赖树加载后的完整文件关系生成的,因此rules中只需要处理真正的依赖文件,node_modules文件应该排除。

rules: [
        {
          test:/.js$/,
          exclude:/node_modules/,
          use:{
            loader:'babel-loader',
            options:{
              presets:['@babel/preset-env']
            }
          }
        }
       ]
plugins:[
	new HtmlWebpackPlugin({
		title:'自定义title',
		meta:{
			viewport:'width= device-width'
		},
		template:'./src/index.html'
	})
]

./src/index.html模板文件通过lodash模板语法输出

<h><%= htmlWebpackPlugin.options.title %></h>

每个htmlWebpackPlugin实例对象都会生成一个对应的页面文件。如果需要多个页面,可实例多个对象,filename指定页面文件的名称。

plugin通过钩子机制实现

自动编译

–watch模式下,文件发生变化时会进行自动编译打包

webpack --watch

自动刷新浏览器

先安装browser-sync,命令行中以browser-sync命令运行,当文件变化时会自动刷新浏览器。

原理是监听 --flies指定文件,发生变化时,刷新浏览器,渲染dist目录下的index.html文件。因此index.html在每次打包时不可删除,如果使用了CleanWebpackPlugin插件,需要配置不删除index文件。

new CleanWebpackPlugin({cleanStaleWebpackAssets: false})
browser-sync  dist --files "**/*"

webpack dev serve

提供用于开发的HTTP Server,集成自动编译和自动刷新浏览器等功能。
首先通过yarn add安装

tips:注意与webpack版本兼容问题,最好安装低版本。webpack4.x ,webpack-cli3.x,webpack-dev-server2.x的组合能很好地兼容。

yarn add webpack-dev-server --dev

命令行运行

yarn webpack-dev-server --config ./webpack.config.js --open

默认打包生成的文件都是服务器资源文件,服务器都可直接访问。但是其他静态资源文件如果也需要作为服务器文件,需要额外配置。具体通过devServerde contentBase设置静资源文件的位置。

module.exports = {
	sevServer:{
		contentBase:'./public'
	}
}

Source Map

Source Map顾名思义,源代码地图,用于映射打包转换后的代码与源代码的关系。
devtool用于设置开发工具设置。

devtool:'source-map'

主要有以下几种区分devtool模式的关键词:

  • eval-是否使用eval执行模块代码
  • cheap-Source Map是否包含行信息
  • module-是否能够得到Loader处理前的源代码

一般的选择规律:

  • 开发环境:cheap-module-eval-source-map
  • 生产环境:none

HMR模块热替换

实现HMR的几种方式:

  • 命令行运行时添加–hot参数
webpack-dev-server --hot
  • 通过配置文件开启
    1、配置devServer开启hot热更新
devServer:{
      hot:true
    }

2、运用webpack内置插件

const webpack = require('webpack')
module.exports = {
	plugins:[
		new webpack.HotModuleReplacementPlugin()
	]
}

HMR优化使用

由于替换逻辑无规律,因此webpack中的HMR还需手动处理替换逻辑。

如果已经通过 HotModuleReplacementPlugin 启用了模块热替换(Hot Module Replacement),则它的接口将被暴露在 module.hot 属性下面。

tips:额外处理之后的文件不再会自动刷新,而是会执行设置的热替换逻辑。

accept
接受(accept)给定依赖模块的更新,并触发一个 回调函数 来对这些更新做出响应。

module.hot.accept(
  dependencies, // 可以是一个字符串或字符串数组
  callback // 用于在模块更新后触发的函数
)

注意事项:

  1. 处理HMR代码报错会导致自动刷新
    解决方式:设置devServer的hotOnly:true。处理HMR错误不会回退刷新。
  2. 没启用HMR的情况下,HMR API报错
    解决方式:HMR的处理代码前先判断是否开启了hot插件module.hot
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值