Webpack 基础
为什么要使用Webpack
- 转换ES6语法
- 转换JSX
- CSS前缀补全/预处理器
- 压缩整合
- 图片压缩
前端构建演变
-> ant + YUI Tool -> Grunt -> Fis3
-> Gulp -> Rollup
-> Webpack
-> Parcel
为什么选择Webpack
- 社区生态丰富
- 配置灵活和插件化扩展
- 官方更新迭代速度快
初识Webpack
-
默认的配置文件:webpack.config.js
可以通过webpack –config <指定文件>
-
配置文件组成
module.exports = {
entry:'./src/index.js', //入口文件
output:'./dist/main.js', //打包输出
mode:'production', //环境
module:{
rules:[ //Loader配置
{test:/\.txt$/,use:'raw-loader'}
]
},
plugins:[ //插件配置
new HtmlwebpackPlugin({
template:'./src/index.html'
})
]
}
核心概念
Entry
作为入口配置,简单来说就重那个文件开始打包。
用法:
- 单入口
module.exports={
entry:'./path/file.js'
}
- 多入口
module.exports={
entry:{
app:'./src/app.js',
adminApp:'./src/adminApp.js'
}
}
Output
将打包后的文件输出到哪里。
用法:
- 单出口
module.exports={
entry:'./path/file.js',
output:{
filename:'bundle.js',
path:__dirname+'/dist'
}
}
- 多出口
module.exports={
entry:{
app:'./src/app.js',
adminApp:'./src/adminApp.js'
},
output:{
filename:'[name].js',
path:__dirname+'/dist'
}
}
Loaders
webpack开箱即用只支持js和json这两种文件类型。像VUE,JSX这些webpack是不支持的,所以就有了Loader。简单来说Loaders就是处理文件的。
Loader本身就是一个函数,接收源文件作为参数然后在返回结果。
常见Loader
名称 | 描述 |
---|---|
babel-loader | 转换ES5+的语法(需要babel的配合) |
css-loader | 支持css文件的加载解析 |
less-loader | 将less转为css |
ts-loader | 将ts转为js |
file-loader | 将文件(图片、字体)等打包 |
raw-loader | 将文件以字符串形式导入 |
thread-loader | 多进程打包js和css |
url-loader | 与file-loader功能一样,但是他是可以配置的,简单来说升级版file-loader |
用法
module.exports = {
entry:'./src/index.js', //入口文件
output:'./dist/main.js', //打包输出
mode:'production', //环境
module:{
rules:[ //Loaders配置
{test:/\.txt$/,use:'raw-loader'}
]
}
}
Plugins
增强Webpack的功能,将打包后的文件进行优化、资源管理、环境变量的注入等待。简单来说就是Loaders做不了的用Plugins来做。
作用用整个构建过程。
常用的插件
名称 | 描述 |
---|---|
CommonsChunkPlugin | 将多个出口引用相同的文件进行提取。 |
CleanWebpackPlugin | 清理构建目录 |
ExtractTextWebpackPlugin | 将css从bundle中提取成一个独立的css文件 |
CopyWebpackPlugin | 将文件或文件夹拷贝到构建的目录中 |
HtmlWebpackPlugin | 创建html文件去承载bundle |
UglifyjsWebpackPlugin | 压缩js(默认是开启的不需要配置) |
ZipWebpackPlugin | 将构建资源生成为zip包 |
HotModuleReplacementPlugin | 热更新 |
MiniCssExtractPlugin | 将css提取成独立的文件(与style-loader会产生冲突) |
OptimizeCssAssetsWebpackPlugin | 用于压缩css(配合 cssnano 加载器使用) |
说明:安装插件时要将所有的大写改为小写并且在非第一个大写字母前加短横线-。
用法
module.exports = {
entry:'./src/index.js', //入口文件
output:'./dist/main.js', //打包输出
mode:'production', //环境
module:{
rules:[ //Loader配置
{test:/\.txt$/,use:'raw-loader'}
]
},
plugins:[ //插件配置
new HtmlwebpackPlugin({
template:'./src/index.html'
})
]
}
Mode
mode是在webpack4提出的一个概念,通过mode来指定当前的构建环境,比如:你现在是development(开发)环境,或者是production(生成环境默认).
选项 | 描述 |
---|---|
development | 开发环境 |
production | 生产环境 |
none | 不开启 |
例子
解析ES6
# 安装依赖
npm i -g webpack webpack-cli
npm i -D @babel/core @babel/preset-env babel-loader
# @babel/core babel核心文件(必须安装)
# @babel/preset-env babel用来转换ES5
# babel-loader webpack的loader,调用babel的
//webpack.config.js
module.exports={
entry:"./src/app.js",
output:{
filename:bundle.js,
path:__dirname+'/dist'
},
mode:'development',
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
}
]
}
}
//.babelrc
{
"presets":[
"@babel/preset-env"
]
}
解析CSS
# 安装依赖
npm i css-loader style-loader -D
# css-loader 将css文件打包成commonjs对象
# style-loader 将css-loader打包好的样式通过<style>标签插入到head中
//webpack.config.js
module.exports={
entry:"./src/app.js",
output:{
filename:"bundle.js",
path:__dirname+"/dist"
},
mode:"development",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.css$/,
use:[
'style-loader',
'css-loader'
]
/*注意:
use内的loader执行是从下到上的,
所以先执行css-loader然后才是style-loader*/
}
]
}
}
解析Less
# 安装依赖
npm i css-loader style-loader less-loader less -D
# css-loader 将css文件打包成commonjs对象
# style-loader 将css-loader打包好的样式通过<style>标签插入到head中
# less-loader 是将less转成css
# less less核心(必装),less-loader依赖
//webpack.config.js
module.exports={
entry:"./src/app.js",
output:{
filename:"bundle.js",
path:__dirname+"/dist"
},
mode:"development",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
/*注意:
use内的loader执行是从下到上的,
首先将less转换成css
然后将css转换成js
然后将js封装为style标签
}
]
}
}
解析文件
# 安装依赖
npm i css-loader style-loader file-loader -D
# css-loader 将css文件打包成commonjs对象
# style-loader 将css-loader打包好的样式通过<style>标签插入到head中
# file-loader 将文件解析
//webpack.config.js
module.exports={
entry:"./src/app.js",
output:{
filename:"bundle.js",
path:__dirname+"/dist"
},
mode:"development",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.css/,
use:[
'style-loader',
'css-loader'
]
/*注意:
use内的loader执行是从下到上的,
首先将less转换成css
然后将css转换成js*/
},
{
test:/.(png|jpg|gif|jpeg|ttf|eot)$/,
use:[
'file-loader'
]
}
]
}
}
更好的解析文件
# 安装依赖
npm i css-loader style-loader url-loader -D
# css-loader 将css文件打包成commonjs对象
# style-loader 将css-loader打包好的样式通过<style>标签插入到head中
# url-loader 更好的文件解析,代替file-loader
//webpack.config.js
module.exports={
entry:"./src/app.js",
output:{
filename:"bundle.js",
path:__dirname+"/dist"
},
mode:"development",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.css/,
use:[
'style-loader',
'css-loader'
]
/*注意:
use内的loader执行是从下到上的,
首先将less转换成css
然后将css转换成js*/
},
{
test:/.(png|jpg|gif|jpeg|ttf|eot)$/,
use:[
{
loader:'url-loader',
options:{
limit:10240 //单位B
}
/*
url-loader 与file-loader功能一样,不过他有一定很不错,
可以传入参数:
limit:单位字节,如果文件小于给定的字节大小,就进行
base64转换
*/
}
]
}
]
}
}
自动打包
两种方法:
- 命令行:webpack —watch
- 配置文件:watch:true
原理:
webpack轮询(每隔一定的时间)对当前文件夹下的文件的修改时间进行监听,如果某个文件发生了变化,webpack不会立即打包而是在缓存时间到后才去打包。
//webpack.config.js
module.export = {
watch:true,//开启监听
watchOptions:{
ignored:/node_modules/.//默认为空,表示不对什么文件夹或文件监听,支持正则表达式 aggregateTimeout:300,//监听触发后等300ms后执行打包,默认300ms
poll:1000,//轮询时间,单位ms
}
}
热重载
方法一
webpack-dev-server开发者服务
优势:
- webpack-dev-server不刷新浏览器
- webpack-dev-server文件放到内存
依赖插件:
HotModuleReplacementPlugin
HMRP 是将打包后的文件放到内存里,通过websocket将内容发给浏览器,实现热重载。
操作:
//webpack.config.js
const {HotModuleReplacementPlugin} = require('webpack');
module.exports={
entry:"./src/app.js",
output:{
filename:"bundle.js",
path:__dirname+"/dist"
},
mode:"development",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
},
{
test:/.(png|jpg)$/,
use:[
{
loader:'url-loader',
options:{
linmit:1024
}
}
]
}
]
},
plugins:[
new HotModuleReplacementPlugin()
],
devServer:{
contentBase:'./dist',//服务器根目录
hot:true //是否热重载
}
}
# 执行命令
npm i webpack-dev-server -g
webpack-dev-server --open
# --open 表示打开浏览器
方法二
/**
* 另一种热重载的方法
*/
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config');
app.use(webpackDevMiddleware(
webpack(config),
{
publicPath:config.output.publicPath
}
));
app.listen(8080, () => {
console.log('Example app listening on port 8080!');
});
//Run app, then load http://localhost:8080 in a browser to see the output.
文件指纹
打包后输出的文件名额外添加的后缀字符。
有什么用:
- 文件的版本管理。
- 文件缓存。
文件指纹如何生成
- hash:根据修改时间生成。
- chunkhash:根据entry生成。
- contenthash:根据文件内容生成。
如何用
占位符 | 含义 |
---|---|
[ext] | 后缀名 |
[name] | 文件名称 |
[path] | 文件的相对路径 |
[chunkhash] | 根据entry生成hash |
[folder] | 文件所在的文件夹 |
[contenthash] | 文件内容hash,默认md5 |
[hash] | 同上 |
[emoji] | 随机字符串 |
说明:[hash:8] 8表示截取前8位。
/**
* 生产环境配置
*/
const MiniCssExtractPulgin = require('mini-css-extract-plugin');
module.exports={
entry:"./src/app.js",
output:{
filename:"bundle_[chunkhash:8].js",
path:__dirname+"/dist"
},
mode:"production",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.less$/,
use:[
MiniCssExtractPulgin.loader,/*注意,这个loader时插件提供的*/
'css-loader',
'less-loader'
]
},
{
test:/.(png|jpg)$/,
use:[
{
loader:'file-loader',
options:{
name:'./img/[name]_[hash:8].[ext]'
}
}
]
}
]
},
plugins:[
new MiniCssExtractPulgin({
filename:'[name]_[contenthash:8].css'
})
]
}
文件压缩
文件压缩是将打包后的html、css、js文件进行压缩。
JS压缩
使用UglifyjsWebpackPlugin
这个插件进行压缩,webpack4生成环境下默认是开启的所以不需要配置。
CSS压缩
需要OptimizeCssAssetsWebpackPlugin
插件
需要cssnano
CSS压缩加载器(核心)
# 安装依赖
npm i -D optimize-css-assets-webpack-plugin cssnano
//webpack.config.js
/**
* 生产环境配置
*/
const MiniCssExtractPulgin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
module.exports={
entry:"./src/app.js",
output:{
filename:"bundle_[chunkhash:8].js",
path:__dirname+"/dist"
},
mode:"production",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.less$/,
use:[
MiniCssExtractPulgin.loader,
'css-loader',
'less-loader'
]
},
{
test:/.(png|jpg)$/,
use:[
{
loader:'file-loader',
options:{
name:'./img/[name]_[hash:8].[ext]'
}
}
]
}
]
},
plugins:[
new MiniCssExtractPulgin({
filename:'[name]_[contenthash:8].css'
}),
new OptimizeCssAssetsWebpackPlugin({
/*作用于打包后的文件*/
assetNameRegExp:/.css$/g,
/*匹配打包后的文件*/
cssProcessor:require('cssnano')
/*使用cssnano压缩处理器*/
})
/*
注意:是先有打包文件,才能进行压缩。
*/
]
}
HTMlL压缩
通过使用HtmlWebpackPlugin
,设置参数进行压缩。
html-webpack-plugin配置表:
Name | Type | Default | Description |
---|---|---|---|
title | {String} |
`` | 用于生成的HTML文档的标题 |
filename | {String} |
'index.html' |
要写入HTML的文件。默认为“index . html”。您也可以在这里指定子目录 (eg: assets/admin.html ) |
template | {String} |
`` |
webpack 需要模板的路径。Please see the docs for details |
templateParameters | {Boolean|Object|Function} |
`` | 允许覆盖模板中使用的参数。 |
inject | {Boolean|String} |
true |
true || 'head' || 'body' || false 将所有资产注入给定的模板”或“templateContent”。当传递“true”或“body”时所有javascript资源都将放在body元素的底部。 'head'`将脚本放在head元素中 |
favicon | {String} |
`` | 将给定的favicon路径添加到输出HTML |
meta | {Object} |
{} |
允许注入“meta”标签。 E.g. meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}
|
minify | {Boolean|Object} |
true |
传递html-minifier的选项作为对象来缩小输出 |
hash | {Boolean} |
false |
如果“true”,则在所有包含的脚本和CSS文件中附加一个惟一的“webpack”编译散列。这对于缓存破坏非常有用 |
cache | {Boolean} |
true |
只有在文件被更改时才发出该文件 |
showErrors | {Boolean} |
true |
错误细节将被写入HTML页面 |
chunks | {?} |
? |
允许您只添加一些块(e。g只是单元测试块) |
chunksSortMode | {String|Function} |
auto |
允许控制块在包含到HTML之前应该如何排序。允许的值是 'none' | 'auto' | 'dependency' | 'manual' | {Function}
|
excludeChunks | {Array.<string>} |
`` | 允许你跳过一些块(e.g不要添加单元测试块) |
xhtml | {Boolean} |
false |
如果“true”将“link”标记呈现为自关闭(XHTML兼容) |
miniify配置表:
默认情况下,大多数选项都是禁用的。
Option | Description | Default |
---|---|---|
caseSensitive |
以区分大小写的方式处理属性(对自定义HTML标记很有用) | false |
collapseBooleanAttributes |
从布尔属性中省略属性值 | false |
collapseInlineTagWhitespace |
折叠时,不要在display:inline; 元素之间留下任何空格。必须与collapseWhitespace = true 一起使用 |
false |
collapseWhitespace |
折叠有助于文档树中文本节点的空白 | false |
conservativeCollapse |
始终折叠到1个空格(永远不要完全删除)。必须与collapseWhitespace = true
|
一起使用FALSE
|
continueOnParseError |
处理解析错误 而不是流失。 | false |
customAttrAssign |
允许支持自定义属性赋值表达式的正则表达式数组(e.g. '<div flex?="{{mode != cover}}"></div>' ) |
[ ] |
customAttrCollapse |
正则表达式,指定从中删除换行符的自定义属性 (e.g. /ng-class/ ) |
|
customAttrSurround |
允许支持自定义属性环绕表达式的正则表达式数组 (e.g. <input {{#if value}}checked="checked"{{/if}}> ) |
[ ] |
customEventAttributes |
允许支持自定义事件属性的正则表达式数组minifyJS (e.g. ng-click ) |
[ /^on[a-z]{3,}$/ ] |
decodeEntities |
尽可能使用直接Unicode字符 | false |
html5 |
根据HTML5规范解析 | true |
ignoreCustomComments |
一组正则表达式,允许在匹配时忽略某些注释 | [ /^!/ ] |
ignoreCustomFragments |
允许在匹配时忽略某些片段的正则表达式数组 (e.g. <?php ... ?> , {{ ... }} , etc.) |
[ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ ] |
includeAutoGeneratedTags |
插入HTML解析器生成的标签 | true |
keepClosingSlash |
在单例元素上保留尾部斜杠 | false |
maxLineLength |
指定最大行长度。压缩输出将在有效HTML分割点处按换行符分割 | |
minifyCSS |
在样式元素和样式属性中缩小CSS (uses clean-css) |
false (可能 true , Object , Function(text, type) ) |
minifyJS |
缩小脚本元素和事件属性中的JavaScript(使用 UglifyJS) |
false (could be true , Object , Function(text, inline) ) |
minifyURLs |
缩小各种属性中的URL(uses relateurl) |
false (could be String , Object , Function(text) ) |
preserveLineBreaks |
当标记之间的空格包含换行符时,始终折叠为1换行符(从不完全删除它)。必须与collapseWhitespace = true 一起使用 |
false |
preventAttributesEscaping |
防止转义属性值 | false |
processConditionalComments |
通过minifier处理条件注释的内容 | false |
processScripts |
与通过缩小器处理的脚本元素类型相对应的字符串数组(例如text/ng-template , text/x-handlebars-template , etc.) |
[ ] |
quoteCharacter |
用于属性值的引用类型(或 ) |
|
removeAttributeQuotes |
尽可能删除属性周围的引号 | false |
removeComments |
剥离HTML注释 | false |
removeEmptyAttributes |
使用仅限空格的值删除所有属性 |
false (could be true , Function(attrName, tag) ) |
removeEmptyElements |
删除所有带空内容的元素 | false |
removeOptionalTags |
删除可选标签 | false |
removeRedundantAttributes |
值匹配默认值时删除属性. | false |
removeScriptTypeAttributes |
从script 标签中删除type =“text /javascript” 。其他type 属性值保持不变false
|
|
removeStyleLinkTypeAttributes |
从style 和link 标签中删除type =“text /css” 。其他type 属性值保持不变false
|
|
removeTagWhitespace |
尽可能删除属性之间的空间。 请注意,这将导致HTML无效! | FALSE |
sortAttributes |
按频率对属性排序 | false |
sortClassName |
按频率对样式类进行排序 | false |
trimCustomFragments |
修剪ignoreCustomFragments 周围的空白区域。 |
false |
useShortDoctype |
用短(HTML5)doctype替换doctype |
false |
//webpack.config.js
/**
* 生产环境配置
*/
const MiniCssExtractPulgin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports={
entry:{index:"./src/app.js"},
output:{
filename:"bundle_[chunkhash:8].js",
path:__dirname+"/dist"
},
mode:"production",
module:{
rules:[
{
test:/.js$/,
use:'babel-loader'
},
{
test:/.less$/,
use:[
MiniCssExtractPulgin.loader,
'css-loader',
'less-loader'
]
},
{
test:/.(png|jpg)$/,
use:[
{
loader:'file-loader',
options:{
name:'./img/[name]_[hash:8].[ext]'
}
}
]
}
]
},
plugins:[
new MiniCssExtractPulgin({
filename:'[name]_[contenthash:8].css'
}),
new OptimizeCssAssetsWebpackPlugin({
assetNameRegExp:/.css$/g,
cssProcessor:require('cssnano')
}),
new HtmlWebpackPlugin({
title:'webpack学习',
template:path.join(__dirname,'src/index.html'),
filename:'index.html',
chunks:['index'],
/**
* 这里需要注意一下,如果entry写法是这样的:{index:'src/index.js'}那这里就需要使用chunks:['index']
* 如果entry写法是: 'src/index.js' 那这里就不需要使用chunks
*
* 如果不按照上面的规定,下面的inject:true将不会生效
*/
inject:true,
/**自动注入js与css */
minify:{
html5:true,
collapseWhitespace:true,
preserveLineBreaks:false,
minifyCSS:true,
minifyJS:true,
removeComments:false
}
})
]
}
结束
到这里webpack的基础用法已经写完了,接下来我会继续更新,webpack的进阶用法。
如果你感觉我的文章对你有用,你可以点下面的大拇指给我鼓励,谢谢。
如果想要转载,请标明出处
网友评论