前言
关于版本,我们讲述的是 webpack 4.0 版本
我希望大家在用 webpack 前,要搞清楚,我们为什么要用 webpack ,它存在的意义是什么?
webpack 基础概念
webpack 可以把它理解为一款工具,一款帮助我们打包的工具,也可以称之为前端构建工具。
简单来说 webpack 做的事情就是将一些特别复杂且浏览器无法识别东西,通过 webpack 编译、打包后,生成了浏览器可以识别的静态资源。
webpack 都能做哪些事情,举几个栗子:
- 文件打包(代码合并)
- 文件压缩(压缩体积)
- 代码转换(scss,less,es6)
- 代码分割(公共模块抽离)
- 模块合并(公共模块合并)
- 热更新(自动刷新)
- 代码校验
- 自动发布
我们需要做的就是在配置文件中写好配置,然后剩下的工作 webpack 会帮我们自动处理。
在使用 webpack 前,我们需要安装 Node.js
与 npm
,webpack 是基于node
编写的,而npm
则用来安装依赖。
webpack 文件结构
在安装开始前,我先说两个文件,以及它们的作用。
package.json
在安装 webpack 前,我们需要初始化一个 package.json 文件,它是项目的描述文件,它的内容是一个json
对象。
例如:
- 项目名称(name)
- 项目版本号(version)
- 项目描述 (description)
- npm 命令(scripts)
- 项目依赖(dependencies)
package.json 可以手工编写,也可以用npm
命令自动生成。
{
//项目名称
"name": "chom",
//版本号
"version": "1.0.4",
//项目描述
"description": "前端基础工具库",
//入口文件
"main": "dist/chom.min.js",
//依赖模块,生产模式
"dependencies": {},
//项目开发所需要的模块,以及版本,开发模式
"devDependencies": {
"@babel/cli": "^7.7.4",
"@babel/core": "^7.7.4",
"babel-loader": "^8.0.6",
"eslint": "^6.7.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
},
//npm 命令行缩写
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
//比如 npm run build
"build": "webpack --config build/webpack.config.js",
"lint": "eslint src/**"
},
//作者
"author": "Zhangwenqiang",
//项目许可证
"license": "ISC"
}
webpack.config.js
webpack 默认会读取 webpack.config.js 文件的配置信息,可以在webpack 源码中修改默认文件名,也可以按环境区分将webpack.config.js 拆分成多个文件,例如:webpack.base.js 、webpack.dev.js 、webpack.prod.js
webpack 结构组成
在了解 webpack 使用配置时,我们必须首先要熟悉 webpack 中几个的核心概念。
mode
在 webpack 中有两种常见的模式,一种是 development
(开发模式),一种是 production
(生产模式)
module.exports = {
mode: 'development'
}
entry
entry
是 webpack 的入口文件
// 单个入口文件的简写语法
module.exports = {
entry: './src/index.js' // entry 属性指定入口文件路径
};
output
output
是 webpack 打包之后输出的文件
// 单个入口文件的简写语法
module.exports = {
entry: './src/index.js',
output: { // output 属性指定打包之后的文件放在什么位置
// filename 属性指定输出文件的文件名称
filename: 'bundle.js',
// path 属性指定输出目录的绝对路径
path: '/dist'
}
};
loader
loader
用于对模块的源代码进行转换
因为 webpack 只能理解 JavaScript
,所以需要 loader
将其它类型的文件转化为 webpack 能够处理的有效模块
不同的 loader
完成不同的任务,下面的例子指定使用 css-loader
处理 CSS
文件
npm install --save-dev css-loader
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' }
]
}
};
plugins
plugin
用于处理一些拓展任务,从打包优化和压缩,一直到重新定义环境中的变量
// 在打包过程中会使用UglifyJsPlugin这个插件来对代码进行一些压缩整理等
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
}
webpack 安装流程
具体的安装流程 webpack的安装和配置 .
大概流程是下载node.js
,初始化项目,安装 webpack 与 webpack-cli
webpack 配置概念
这里我会介绍一些 webpack 常用插件的概念以及为什么要使用这些插件。
html-webpack-plugin
简单来说 html-webpack-plugin 的基本作用就是生成html
文件。
前面提到过,webpack 默认只能处理 javascript
文件,显然我们的项目中不可能只存在js
文件,我们需要 webpack 将html
也进行打包处理,这个时候就需要用到 html-webpack-plugin
html-webpack-plugin 还有一个重要的作用是会将html
文件中引入的外部资源,自动创建一个正确的路径。
例如a.html
引入了 a.js
,但通过 webpack 打包会把a.js
与其他js
文件进行打包,而a.html
引入的路径已经失效,此时 html-webpack-plugin 会自动将a.html
引入的文件路径修改成已经打包后的文件路径。
具体的使用方法 html-webpack-plugin的使用
样式处理
webpack 处理css
文件一般需要用到 css-loader
与 style-loader
css-loader
的作用是解析css
中的import
、url
、require
之类的语法,帮我们分析出各个css
文件之间的关系,把各个css文件合并成一段css
style-loader
的作用是将css-loader
生成的css
代码挂载到页面的header
部分,见下图:
如果项目中用到了scss
或者less
,都需要安装想对应的loader
,具体的使用方法 webpack 打包样式
转化es6语法
为什么要处理es6
语法?
es6
语法并不是所有浏览器都支持、都能运行,一些浏览器如果不支持那么就会报错,导致用户体验非常糟糕,这个时候我们就需要使用babel
来将es6
语法处理成es5
语法,比如箭头函数
、map()
等语法特性,转换成浏览器能够识别的,低级的JS
语法,就可以解决这个问题。
关于es6
的兼容性,大概是这个样子滴:
Chrome 51
版起便可以支持97%
的ES6
新特性。Firefox 53
版起便可以支持97%
的ES6
新特性。Safari 10
版起便可以支持99%
的ES6
新特性。IE Edge 15
可以支持96%
的ES6
新特性。Edge 14
可以支持93%
的ES6
新特性。(IE7~11
基本不支持ES6
)win10
之后的浏览器是edge
。之前的是IE
。
具体的使用方法 webpack编译ES6
处理js语法校验
提到js语法校验,不得不提到 eslint
eslint
是什么?为什么我们要在项目中使用 eslint
eslint
是一个语法规则和代码风格的检查工具
它可以检测我们编写的代码,给代码一个规范,项目中的代码必须按照这个规范编写
统一代码规范对我们有哪些好处?
- 有些格式上的问题会导致我们在发布生产环境时出现一些莫名的错误
- 团队协作,团队保持同一个风格编写代码,代码的可读性以及可维护性都较为友好
具体使用的方法 webpack引入eslint详解
全局变量引入
做项目时我们可能会遇到这种场景:一个变量很多文件中都会用到,这变量可能是第三方包(比如 Jquery
),也可能是自己定义的一个工具类。
这种情况我们怎么办?难道要在所有页面中都引用这个变量吗?答案是否定的,这样会造成项目的维护成本很高。
那么我们该如何高效便捷的引入全局变量呢,其实有两种方式。
- 使用 webpack 模块 注册全局变量
- 将变量暴露给
window
对象 成为全局变量
这里要注意一下,webpack 是一个工具,在这个工具里面,有一个同名的模块,叫做 webpack,我们就用这个模块给每一个页面或者组件注入一个对象。
//以jquery为例
let Webpack = require('webpack') // 引入webpack模块
module.exports = {
plugins: [ // 这是一个插件,所以要在plugins属性中配置
new Webpack.ProvidePlugin({
$: 'jquery'
})
],
}
这样我们直接就可以在页面或组件中直接使用jquery
,例如:
console.log($)
第二种方法,我在这里就不阐述了,感兴趣的同学可以自行搜索,我个人还是比较喜欢用第一种方法的(主要是懒,有点写不动了)。
图片处理
webpack 在处理图片上通常会使用 file-loader
、url-loader
file-loader
的作用
file-loader
可以用来帮助 webpack 打包处理 png
jpg
jepg
等格式的图片;
file-loader
打包图片会生成一个hash
值作为图片的名字;
url-loader
的作用
url-loader
可以将图片转换成base64
的图片格式,可以减少网站的http
请求,但是若是相同图片被引用多次,每一次都转换成base64
,会造成js
性能损耗,因此是将图片资源转换为base64
还是采用 http
的方式,要看图片具体的使用方式了。
这里要注意一下,url-loader
内部封装了file-loader
,url-loader
不依赖于file-loader
,即使用url-loader
时,只需要安装url-loader
即可,不需要安装file-loader
。
打包文件分类
在使用 webpack 打包时,可能要将css
归类到css
目录下,img
归类到img
目录下,我们也可能会在引用资源的时候加上域名前缀,这时候就用到了我们的打包文件分类。
给图片归类到img
目录下
rules:[
{
test:/\.(png|jpg|gif)$/,
use:{
loader:'url-loader',
options:{ limit:2,//200k,小于200k使用base64来转换
outputPath:'/img/'//大于上面的limit的图片就会生成到dist下的img文件夹下,同时所有路径都会加上这个img/
}
}
}
]
给css
归类到css
目录下
plugins:[
new MiniCssExtractPlugin({
filename:'/css/[name].[chunkhash:8].css',//抽离出来的css的文件名称,并在dist下生成css文件夹,将该文件放到该css目录下,引入的时候会自动加上/css/
})
]
对所有输出资源加域名前缀,在引用的资源前,统一加上这个额publicPath
,比如打包后的css
路径是 /css/main.css
,那么引用的时候就会成为publicPath
值+ /css/main.css
output:{
filename:'bundle.[hash:8].js',
path:path.resolve(__dirname,'./dist'),
publicPath:'http://www.yuhua.com',//在引用的资源前,统一加上这个额publicPath,比如打包后的css路径是css/main.css,那么引用的时候就会成为publicPath值+'css/main.css'
},
结语
文章断断续续大概用了两周左右完成的,全当是自己对 webpack 知识点的复习与总结了,在这里吐槽一句(写文章真的很累),后续会更新 webpack 核心配置篇、webpack 性能优化篇.
感谢看到这篇文章的你,烦请帮忙为我的文章点几个赞同,让更多需要的朋友看到,非常感谢。
已工作的,祝您工作顺利,事业有成!还在学习的,祝您一切顺利,学业有成!