一、 什么是webpack
1、官方解释
本质上讲, webpack 是一个现代 JavaScript 应用程序的静态模块打包器。(模块和打包)
2、前端模块化
- 前端模块化的一些方案: AMD、 CMD、 CommonJS、 ES6
- 浏览器不能识别它们, 但是webpack 可以做它们的底层支撑,方可进行模块化开发
- ES6 之前, 要想进行模块化开发, 就必须借助于其他的工具, 让我们进行模块化开发
- 并且通过模块化开发完成了项目后, 还需要处理模块化间的各种依赖, 并且将其进行整合打包
- 此时出现 webpack, 其中一个核心就是让我们可能进行模块化开发, 并且会帮助我们处理模块间的依赖关系。
- 而不仅仅是JavaScript文件,我们的css、图片、json 文件等等在webpack 中都可以被当作模块来使用
3、打包如何理解
- webpack 可以帮助我们进行模块化, 并且处理模块间的各种复杂关系后, 打包的概念就很好理解了
- 就是将 webpack 中的各种资源模块进行打包合并成一个或多个包(bundle)
- 并且在打包的过程中, 还可以对资源进行处理, 比如压缩图片, 将scss 转成 css, 将ES6 语法转成ES5 语法, 将TypeScript 转成 JavaScript 等等操作
- 打包工具还有 grunt/gulp
- webpack 和 grunt/gulp 的对比
- grunt/gulp 的核心是Task
- 可以配置一系列的task, 并且定义 task 要处理的事务(例如 ES6、ts转化、图片压缩、scss转成css)
- 之后让grunt/gulp 来依次执行这些task, 而且让整个流程自动化
- 看一个gulp 的 task
- 下面的task 就是将src 下面的所有js 文件转成 ES5 的语法
- 并且最终输出到dist 文件夹中
- 什么时候使用grunt/gulp?
- 工程模块依赖非常简单, 甚至没有用到模块化的概念
- 只需要进行简单的合并、压缩, 就使用grunt/gulp 即可
- 如果整个项目使用了模块化管理, 而且相互依赖非常强, 我们就可以使用webpack
- grunt/gulp 和 webpack 有什么不同
- grunt/gulp 更加强调的是前端流程的自动化, 模块化不是它的核心
- webpack 更加强调模块化开发管理, 而文件压缩合并、预处理等功能, 是她附带的功能
- grunt/gulp 的核心是Task
二、webpack 安装
webpack 为了正常运行必须依赖node 环境, 而node 环境为了可以正常执行,必须使用 npm 工具管理 node中各种依赖包
- 因此 安装webpack 首先要安装Node.js, Node.js 自带了软件包管理工具 npm
- 全局安装 webpack (npm install webpack@3.6.0 -g)
局部安装 webpack (npm install webpack@3.6.0 —save-dev) —save-dev 是开发时依赖,项目打包后不再需要继续使用
三、webpack 的配置
1、文件和文件夹解析
dist文件夹: 用于存放打包之后的文件
- src 文件夹: 用于存放我们写的源文件
- main.js 项目的入口文件
- mathUtils.js 定义了一些数学工具函数, 可以在其他地方引用, 并且使用
- index.html 浏览器打开展示的首页html(在这里引用的是 src 内最终打包的文件 即 dist 文件夹的内容)
- package.json 通过npm init 生成的, npm 包管理文件
(CommonJS模块化规范, CommonJS 是模块化的标准, nodejs 就是 CommonJS 模块化的实现)
2、命令
webpack ./src/main.js ./dist/bundle.js (将 main.js 文件打包成 bundle.js 文件)
说明: 也可以使用 ES6 的模块化规范
// 使用commonjs 的模块化规范
const { add, mul } = require('./mathUtils.js')
console.log(add(20, 30));
console.log(mul(20, 30));
// 使用 ES6 的模块化规范
import { name, age, height } from './info'
console.log(name);
console.log(age);
console.log(height);
3、创建 webpack.config.js 文件简化打包命令
(将打包命令映射为打包入口和出口)
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
- entry: 为打包的入口
- output: 为打包的出口
- output 中的path 我们需要动态获取
- 因为我们可以使用Node.js 语法导入一个模块这个模块path [ const path = require(”path”)] 引号内的文件是需要在node 包里找到
- 通过npm init 命令(初始化)使用node.js
- 之后生成 package.json 文件(该文件描述当前项目的信息)
- license: “ISC” 为开源项目
说明: 如果想使用node, 必须依赖于 package.json 文件
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \'Error: no test specified\' && exit 1"
},
"author": "",
"license": "ISC"
}
运行 npm install webpack@3.6.0 —save-dev 之后,增加了如下依赖
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \'Error: no test specified\' && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^3.6.0"
}
}
4、将webpack 命令映射 npm run
除了将 webpack 映射入口、出口之外, 还可以将webpack 命令映射为 npm run 一些操作(需要在 package.json 内”script” 脚本标签中修改)
四、loader 的使用
1、什么是loader
- loader 是webpack 中一个非常核心的概念
webpack 用来做什么?
- 主要用webpack 处理js代码, 并且 webpack 会自动处理 js 之前相关的依赖
- 但, 在开发中不仅要处理js代码, 还需要加载css、图片,一些高级的如将 ES6 转成ES5代码, 将 scss、less 转成 css, 将jsx、.vue 文件转成js 文件等
- 对于webpack 本身的能力来说,这些转化是不支持的
此时可以交给 webpack 扩展 对应的 loader 来处理
2、loader 使用示例
示例1: css 文件处理
通过 npm 安装需要使用的loader
- npm install —save-dev css-loader
- npm install —save-dev style-loader
在 webpack.config.js 中的modules 关键字下进行配置
安装对应的loader
- npm install —save-dev less-loader less(安装less 是 对less 文件进行编译)
- 修改对应的配置文件, webpack.config.js 文件中的rules 数组中新增一个对象处理.less 文件
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
// 当加载的图片,小于limit 时, 会将图片编译成 base64 字符串形式
// 当加载的图片,大于limit 时, 需要使用file-loader 模块进行加载
limit: 8196
}
}
]
}
打包后会发现dist文件夹下多了一个图片文件
说明
- webpack 会自动帮我们生成一个非常长的名字
- 这是一个 32位 hash值, 目的是防止名字重复
- 但是实际开发中, 可能对打包的图片名字有一定的要求
- 可以在options 中添加如下选项
- img: 文件要打包到的文件夹
- name: 获取图片原来的名字,放在该位置
- hash8: 为了防止图片名字冲突, 依然使用hash, 但只保留8位
- ext: 使用图片原来的扩展名
另外, 配置图片修改图片使用的路径可以在 output 下的 publicPath 中配置{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
// 当加载的图片,小于limit 时, 会将图片编译成 base64 字符串形式
// 当加载的图片,大于limit 时, 需要使用file-loader 模块进行加载
limit: 8196,
name: 'img/[name].[hash:8].[ext]'
}
}
]
}
示例4: ES6转ES5的babel
npm install —save-dev babel-loader@7 babel-preset-es2015
配置webpack.config.js 文件
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
option: {
presets: ['es2015']
}
}
}
重新打包后,会发现 bundle.js 文件内容变成了es5 的语法
五、plugin 的使用
HtmlWebpackPlugin | webpack 中文文档
1、认识plugin
- plugin 是什么?
- plugin 是插件的意思, 通常是用于对某个现有的架构进行扩展
- webpack 中的插件, 就是对webpack现有功能的各种扩展, 比如打包优化、文件压缩等
- loader 和 plugin区别
- loader 主要用于转化某些类型的模块, 他是一个转化器
- plugin 是插件, 他是对webpack本身的扩展, 是一个扩展器
- plugin 的使用过程
- 通过npm 安装需要使用plugins (某些webpack已经内置的插件不需要安装)
- 在 webpack.config.js 中的plugins中配置插件
2、webpack 添加版权信息 Plugin 的使用
使用插件, 为打包的文件添加版权声明, 该插件名字叫 BannerPlugin, 属于 webpack 自带的插件
const path = require('path')
const webpack = require('webpack')
module.exports = {
...
plugins: [
new webpack.BannerPlugin('最终版权归coderwhy所有')
]
}