webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
一、webpack 的五个核心概念
Entry
入口指示,表示webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。
Output
输出指示,表示webpack打包后的资源 bundles 输出到哪里去,以及如何命名。
Loader
Loader能够让webpack去处理那些非js和json文件。webpack自身只能处理js和json文件。
plugins
插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
Mode
模式指示,webpack 使用相应模式的配置。只有两个值:development 和 production。
二、Getting Started
全局安装或升级 webpack
npm install webpack webpack-cli -g
初始化 package.json
创建项目文件夹并进入,然后键入:
npm init 或 npm init -y
下载并安装 webpack 开发依赖
npm install webpack webpack-cli -D
webpack命令
webpack --help #帮助命令
webpack -v #版本信息
编译打包应用
webpack --entry ./src/index.js -o ./build --mode development
webpack 会以 ./src/index.js为入口文件开始打包,打包后输出到 ./build 目录下,整体打包环境为 开发环境。
webpack --entry ./src/index.js -o ./build --mode production
webpack 会以 ./src/index.js为入口文件开始打包,打包后输出到 ./build 目录下,整体打包环境为 生产环境。
注意:
1、webpack 可以打包js和json 资源,不能直接处理css和img等其他资源。
2、生产环境会比开放环境多一个压缩js代码。
3、生产环境和开发环境会将ES6模块化编译成浏览器识别的模块化。
三、webpack 开发环境的基本配置
在项目的根目录下需手动创建webpack.config.js文件。结构如下:
/**
* webpack.config.js 为webpack的配置文件
* 当运行webpack指令时,会加载里面的配置
*/
/**
* 所有的构建工具都是基于nodejs平台运行的。模块化默认采用commonjs
*/
//resolve 是用来拼接绝对路径的方法
const { resolve } = require('path');
module.exports = { //webpack配置
//入口启点
entry: "./src/index.js",
//输出
output: {
filename: "js/index.js", //输出文件存放的目录及文件名
//__dirname 是nodejs的变量,代表当前文件的目录的绝对路径
path: resolve(__dirname, 'build'),
//Not all ecosystem tooling is ready for the new default automatic
publicPath via output.publicPath: "auto"
//Use a static output.publicPath: "" instead.
publicPath: ""
},
//loader的配置
module: {
rules: []
},
//插件的配置
plugins: [
],
//模式
// mode:"production",
mode: "development"
};
打包css资源的配置
module.exports = {
//loader的配置,不同文件资源必须配置不同的loader处理
module: {
rules: [
//...
{
test: /.css$/i,
use: ["style-loader", "css-loader"]
}
]
}
}
style-loader 的作用是创建style标签将样式引入,css-loader的作用是将css文件整合到js中。
打包less资源的配置
module.exports = {
//省略其他配置
//loader的配置,不同文件资源必须配置不同的loader处理
module: {
rules: [
//省略其他loader的配置
{
test: /.less$/i,
use: ["style-loader", "css-loader", "less-loader"]
}
]
}
}
打包图片资源的配置
module.exports = {
//省略其他配置
module: {
rules: [
//省略其他loader的配置
//处理url图片资源(background: url(./vue.jpg);),但是处理不了html中直接引用的图片资源(<img src="./angular.jpg" alt="" />)
{
test: /.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader', //或 file-loader
options: {
limit: 8 * 1024,
//Specify a filesystem path where the target file(s) will be placed.
outputPath: 'images',
},
},
]
},
//处理html中直接引用的图片资源(<img src="./angular.jpg" alt="" />)
{
test: /.html$/i,
use: "html-loader"
}
]
}
}
html模板资源
html的加载不是通过loader而是使用插件的方式
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
module.exports = {
//loader的配置,不同文件资源必须配置不同的loader处理
//插件的配置
plugins: [
//html-webpack-plugin
//功能:默认会创建一个空的html,并且自动引入打包输出的所有资源
// new HtmlWebpackPlugin(),
//复制./src/test.html文件,并且自动引入打包输出的所有资源
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}
注意:
loader 的使用步骤是: 1、下载 2、使用。而plugins的使用步骤是: 1、下载 2、引入 3、使用
打包其他资源的配置
module.exports = {
//省略其他配置
module: {
rules: [
//省略其他loader的配置
{
//打包除.less .html ....之外的资源文件
exclude: /.(less|html|css|png|jpeg|jpg|gif|js|json|ts)$/i,
loader: 'file-loader',
options: {
//Specify a filesystem path where the target file(s) will be placed.
outputPath: 'media',
},
}
]
}
}
编辑入口文件 ./src/index.js
//导入css资源
import "./style.css";
//导入json资源
import data from "./data.json";
//导入less资源
import "./test.less";
//js资源
console.log(data);
console.log("OK");
下载指定loader和plugin
npm i css-loader style-loader less less-loader html-webpack-plugin file-loader ..... -D
可能一次性下载不全,可以先运行,根据错误提示,继续安装。
然后运行指令:
webpack 或 webpack b 或 webpack bundle
四、开发服务器devServer
devServer用来自动编译、自动打开浏览器和自动刷新页面。
配置如下:
const { resolve, join } = require('path');
module.exports = {
//省略其他配置
devServer: {
contentBase: join(__dirname, 'dist'),
//启动gzip压缩
compress: true,
//访问端口
port: 3000,
//是否自动打开浏览器
open: true
}
};
devServe只会在内存中编译打包,不会有任何输出。
启动devServer的指令为:
webpack serve 或 webpack s
五、开发环境优化-HMR
HMR(hot module replacement):热模块替换。在默认情况下,一个模块任何一点小的改动都会触发devServer全部自动编译和自动刷新页面。HMR的作用是当一个模块发生变化,只会重新打包这个模块,而不是打包所有,从而提高效率。
样式文件:可以使用HMR功能,因为sytle-loader中内部实现了HMR功能。
html文件:默认不使用HMR功能,同时也会导致html文件不更新了,解决办法:修改entry入口,将html文件引入。但是,一般情况下,对于单页面应用不需要对html文件做HMR功能。
js文件:默认不使用HMR功能(更新所有),需要修改入口文件js代码,添加支持HMR功能的代码。
//一旦module.hot有值,说明开启了HMR功能。
if(module.hot){
//监听./test.js文件的变化,一旦发生变化,会执行后面的回调函数。(其他js文件默认就不会重新打包构建了)
module.hot.accept('./test.js',function(){
//....
});
}
注意:
如有要开启HMR功能,需要先检查package.js中是否配置了browserslist选项。如果已配置了browserslist选项,需要将 webpack.config.js中的target指定为web。 target的作用是为webpack指定一个特定的环境,它的默认值是browserslist或web,当package.js中配置了browserslist选项,它的默认值就是browserslist,否则就是web。