初识webpack:配置文件名称
webpack 默认配置文件:webpack.config.js
可通过 webpack --config 指定配置文件
webpack基本配置如下图:
webpack 4.0出来以后称有一个零配置的webpack(也就是我们不需要编写webpack配置,他就会使用默认进行打包)
如上图零配置的webpack 是包含
entry
和output
的,对mode、module、plugins
没有做设定。
环境的搭建,安装webpack。
1.安装webpack 之前需要安装node.js 和 npm 包管理器。
2.node.js 的安装地址 https://nodejs.org (mac可使用nvm来进行指定版本的安装)
3.安装完毕可使用命令node -v
和npm -v
来检查是否安装成功。
4.安装完毕node.js 和npm 之后就可以安装webpack了。webpack 4 里面是将(webpack内核和webpack-cli 进行了一个分离),所以我们在实际项目的时候同时要安装 webpack 和 webpack-cli . 下面代码演示一下。
$ mkdir my_project //创建一个文件夹
$ cd my_project // 进入
$ npm init -y // 初始化一个package.json文件,-y是一切选项默认
$ npm install webpack webpack-cli --save-dev //--save-dev (将依赖添加到devdependencies里面而不是dependencies)
$ ./node_modules/.bin/webpack -v //来检查版本
一个简单的webpack来了解它的使用
/*
* webpack.config.js的基础配置
* 基于以下entry我们需要建一个src的文件夹,并在下面建index.js文件
* 如何运行打包命令: ./node_modules/.bin/webpack
*/
"use strict"
const path = require('path'); //node.js当中的一个内置模块
module.exports = {
entry: './src/index.js', //需要打包的入口文件
output: {
path: path.join(__dirname, '/dist'), //配置路径 __dirname当前文件夹路径
filename: 'bundle.js' //配置output输出来的文件名
},
mode: 'production'
}
指定webpack的运行命令
你是不是会觉得运行打包webpack的命令很长,我们马上来配置一下
在package.json中script 加"build" : "webpack"
webpack核心概念
- entry
Entry用来指定 webpack 的打包入口
为什么用entry作为打包入口,对于webpack的构建机制有很大关系,在webpack眼中所有的资源都是模块,js、html或者是图片文字等。他们都互相依赖形成一个tree。而entry就是作为整个依赖的入口。
定义entry有两种形式:
1.单入口:entry是一个字符串
module.exports={
entry :'./src/index.js'
};
2.多入口:entry是一个对象 (值为key : value)
module.exports={
entry :{
app : './src/app.js',
adminApp:'./src/adminApp.js'
}
};
- output
output用来告诉
webpack
如何将编译后的文件输出到磁盘
/*
* output 用法:单入口配置
* 单入口的filename 可以写死。
*/
module.exports={
entry :'./path/to/me/my/entry/file.js',
output : {
filename : 'bundle.js',
path : __dirname + '/dist'
}
};
/*
* output 用法:多入口配置
* 在output 中针对多入口并没有提供与entry一样的键值对的形式而是通过占位符的形式。'[name].js'
*/
module.exports={
entry :{
app : './src/app.js',
adminApp:'./src/adminApp.js'
},
output : {
filename : '[name].js',
path : __dirname + '/dist'
}
};
- loaders
wbepack 开箱即用只支持JS 和JSON 两种文件类型,通过 Loaders 去支持其他文件类型并且把它们转化成有效的模块,并且可以添加到依赖图中。
本身是一个函数接受源文件作为参数,返回转化的结果
常见的Loaders
Loaders的用法
module.exports={
entry :'./path/to/me/my/entry/file.js',
output : {
filename : 'bundle.js',
path : __dirname + '/dist'
},
module : {
rules :[
{test : /\.txt$/,use : 'raw-loader'} // test 指定匹配规则
] // use 指定使用的 loader 名称
}
};
- plugins
前面的loaders 是用来处理 webpack 不能解析的文件,plugins 是用来增强 webpack的。
plugins 插件用于打包完文件的优化,资源管理和环境变量的注入 (你可以理解为loaders完成不了的都由plugins完成)
作用于整个构建过程
常见的plugins有哪些
/*
* plugins 的用法
*/
module.exports={
entry :'./path/to/me/my/entry/file.js',
output : {
filename : 'bundle.js',
path : __dirname + '/dist'
},
plugins : [
new HtmlWebpackPlugin({template : './src/index.html'}) // 对于多个插件我们都放到plugins 数组里面
]
};
- mode
mode 用来指定当前打包的环境 :production、development 还是none (在webpack 4 以前是没有mode这个概念的)
设置mode可以使用 webpack 内置的函数,默认值为production。(如果没有设置webpack什么都不会做)
mode 的内置函数功能
webpack是如何来解析ES6和 React JSX
原生的webpack是支持js的但是对于ES6的特殊语法 webpack 并不是很了解。
首先 如上我们需要在rules 里面进行配置(test:匹配文件,use:指定使用的loader),babel-loader是依赖于babel(因此我们需要在项目中使用babel的配置文件.babelrc
中增加es6的babel preset 配置)
介绍一下 babel 主要有两个比较重要的概念
- preset (是一系列babel plugins的集合)
- plugins (你可以理解为一个plugin对应一个功能)
这里我们要解析ES6 我们只需要安装"@babel/preset-env"
/*
* 用命令
*/
npm i @babel/core @babel/preset-env babel-loader -D //-D是 --save-dev的简称
npm @babel/preset-react //用来解析jsx
webpack 解析css
module.exports = {
entry: {
index: './src/index.js',
search: './src/search.js'
},
output: {
path: path.join(__dirname, '/dist'),
filename: '[name].js'
},
mode: 'production',
module: {
rules: [{ test: /\.js$/, use: 'babel-loader' },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] } //css 是链式调用,执行顺序是从右到左所以要先写style-loader
]
}
}
css-loader 用于加载 .css 文件,并且转化成 commonjs对象
style-loader 将样式通过<style> 标签插入到head中
解析Less和Sass
less-loader
用于将less转换成css
/*
* npm i less less-loader -D //因为less-loader 是依赖于less的
*/
module: {
rules: [{ test: /\.js$/, use: 'babel-loader' },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /.less/, use: ['style-loader', 'css-loader', 'less-loader'] }
]
}
如何解析图片和字体
解析图片和字体都可使用 file-loader 来进行处理
module: {
rules: [{ test: /\.js$/, use: 'babel-loader' },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /.less/, use: ['style-loader', 'css-loader', 'less-loader'] },
{ test: /.(png|svg|jpg|jpeg|svg)/, use: 'file-loader' },
{ test: /.(woff|woff2|eot|ttf|otf)/, use: 'file-loader' }
]
}
除此之外还可以使用
url-loader
他会对于小于限定大小的资源(小图片或小字体进行base64的转换),它内部也是用了file-loader的。
module: {
rules: [{ test: /\.js$/, use: 'babel-loader' },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /.less/, use: ['style-loader', 'css-loader', 'less-loader'] },
{ test: /.(png|svg|jpg|jpeg|svg)/, use: 'file-loader' },
{ test: /.(woff|woff2|eot|ttf|otf)/, use:[loader : 'url-loader' ,options : {limit : 10240}]}
]
}
/*
* url-loader 他会接受一个参数通过options来传进去。
* limit 单位是字节。10240代表10k 小于10k他会进行base64的转换
*/
webpack中的文件监听
文件监听是在发现源代码发生变化时,自动重新构建出新的输出文件。
webpack 开启监听模式,有两种方式:
- 启动 webpack 命令时,带上 --watch 参数 (唯一缺陷:每次需要手动刷新浏览器)
在配置 webpack.config.js 中设置 watch : true
文件监听的原理和分析
简单介绍文件监听,webpack 会轮询判断文件的最后编辑时间是否发生变化,一开始我们会有一次文件修改时间,他会把这个时间存储起来,下一次再有修改他会和上一次做对比如果发生变化它不会立刻告诉监听者,而是先缓存起来。监听等待。轮询的时间由poll控制。
webpack中热更新及原理分析
webpack-dev-server 对比 --watch 的优点 经常与HotModuleReplacementPlugin 一起使用
还有一种方式 webpack-dev-middleware 这种需要自己配置比较灵活。(可移步官网查看)
热更新的与原理分析
热更新分两个阶段一个是起步还有就是热更新
起步阶段是1/2、A、B,更新是1,2,3,4,5
文件指纹策略 (文件指纹不能和热更新一起使用)
什么是文件指纹? (打包后输出的文件名的后缀)
用处?(版本的管理、合理的运用缓存)
如何生成
contenthash
根据文件内容来定义hash,内容不变则contenthash不变,通常用于css打包,避免受同一个chunk的js文件修改的影响。配合MiniCssExtractPlugin使用,MiniCssExtractPlugin和style-loader是互斥的
图片的文件指纹
代码压缩主要有三个部分 (HTML、CSS、JS)
- js文件的压缩 (webpack内置了
uglifyjs-webpack-plugin
)
我们打包好的js默认都是压缩的,所以我们不需要再做什么了(当然你也可以下载这个插件为这个下载一些其他的参数)
- css的压缩
需要配合
cssnano
来使用。
-
html的压缩
自动清理构建目录产物
const CleanWebpackPlugin = require('clean-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
的问题。 v3升级完只剩一种方式解构了
主要是clean-webpack-plugin这个插件进行了大版本升级
PostCSS插件autoprefixer自动补全CSS3前缀
使用
npm i postcss-loader autoprefixer -D
以下是 autoprefixer 更新后的新的书写格式 (官方推荐写在package.json中)
官方推荐写法
{
"private": true,
"dependencies": {
"autoprefixer": "^6.5.4"
},
"browserslist": [
"last 1 version",
"> 1%",
"IE 10"
]
}
························
// 通过配置 .browserslistrc 来使用
{ loader: 'postcss-loader',
options: { plugins: () => [require('autoprefixer')] //他会自动去寻找 .browserslistrc 这个
}
}
// 如果想直接设置也可以改成 overrideBrowserslist (这样终端不会报错)
{ loader: 'postcss-loader',
options: { plugins: () => [require('autoprefixer')({ overrideBrowserslist: ['ios 7' , ' last 2 version ']})]
}
}
移动端css px自动转成rem
CSS 媒体查询实现响应式布局
css3 提出了rem 的单位 (rem是什么?) ,webpack中也有相应的loader
W3C 对rem 的定义:font-size of the root element
rem 和 px 的对比:(.rem是相对单位 , .px是绝对单位)
静态资源内联
raw使用的时候要注意使用0.51的这个版本(新版本有些问题)
1.安装
npm i raw-loader@0.5.1 -D // 下载指定版本
2.引入
// html 引入
${require('raw-loader!./meta.html')}
// js引入 (还需要babel-loader来进行解析es6)
${require('raw-loader!babel-loader!./meta.html')}
多页面应用打包通用方案
- 多页面应用(MPA)概念
每一次页面跳转的时候,后台服务器都会给返回一个新的 html 文档,这种类型的网站也就是多页网站,也叫做多页应用
利用glob.sync以同步的方式查询出来
1.安装
npm i glob -D
·····················
// 动态配置entry 和htmlwebpackplugin
const glob = require('glob');
const setMPA = () => {
const entry = {};
const htmlWebpackPlugins = [];
const entryFiles = glob.sync(path.join(__dirname, './src/*/index.js'));
Object.keys(entryFiles)
.map((index) => {
const entryFile = entryFiles[index];
const match = entryFile.match(/src\/(.*)\/index\.js/);
const pageName = match && match[1];
entry[pageName] = entryFile;
htmlWebpackPlugins.push(
new HtmlWebpackPlugin({
template: path.join(__dirname, `src/${pageName}/index.html`),
filename: `${pageName}.html`,
chunks: [pageName],
inject: true,
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
})
)
})
return {
entry,
htmlWebpackPlugins
}
}
const { entry, htmlWebpackPlugins } = setMPA();