概念
本 质上,webpack是一个现代 JavaScript 应用程序的 静态模块打包器(module bundler) 。
当 webpack 处理应用程序时,它会递归地构建一个 依 赖关系图(dependency graph) ,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle 。
安装
nodejs环境下
本地安装
npm install --save-dev webpack
npm install --save-dev webpack-cli
核心概念
- 入口(entry)
- 输出(output)
- loader
- 插件(plugins)
准备文件
-- dist 文件生成目录
---- index.html
-- index.js 主入口文件
-- header.js 需要被index引入的文件
# index.html
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<title>第一个webpack页面</title>
</head>
<body>
<script src="main.js"></script>
</body>
</html>
<!--打包好的js名称默认是main.js-->
# index.js
import {header} from './header.js'
document.body.append(header);
# header.js
var header =document.createElement("div");
header.innerHTML="你好webpack from header";
export {header};
执行命令 打开index.html
npx webpack index.js
// 在你的项目目录执行 这里的名称是 mypack
然后打开你的dist/index.html 查看网页文件
同时你会发现在 dist目录多个main.js这个打包生成好的js文件
使用配置文件
在项目目录 新建一个webpack.config.js
webpack默认配置文件
const path = require('path')
// 引入node的 path路径模块
module.exports={
entry:'./index.js',
// 指定文件的入口
output:{
filename:'main.js',
// 定义文件名
path:path.resolve(__dirname,'dist')
// 定义文件夹
// __dirname获取当前目录
// path.resolve 方法将路径或路径片段的序列解析为绝对路径
}
// 指定打包好的出口
}
// module.export node中导出模块的意思
# 以下为纯净版本
const path = require('path')
module.exports={
entry:'./index.js',
output:{
filename:'main.js',
path:__dirname+'/dist',
}
}
执行命令npx webpack
实现打包
配置 scripts
找到package.js 配置scripts
"scripts":{
start: "webpack"
}
这样我们就可以执行
npm run start
// yarn start
配置模式
const path = require('path')
module.exports={
mode:'development', //开发模式
// mode:'production',// 产品模式
entry:'./index.js',
output:{
filename:'main.js',
path:path.resolve(__dirname,'dist')
产品模式打包的大小要比生产模式要小的多。
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
因为 index.html 文件太死了,连 js 文件都写死了
html-webpack-plugin
安装
npm install html-webpack-plugin --save-dev
使用
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports={
mode:'production',
entry:'./src/index.js',
output:{
filename:'main.js',
path:__dirname+'/dist'
},
plugins:[
new htmlWebpackPlugin({
template:'./src/index.html'
})
]
}
# 项目mypack目录结构如下
src
header.js
index.html
index.js
package.js
webpack.config.js
下面再来介绍几个参数,以及它的结果。
filename: 'index.html' 默认情况下生成的 html 文件叫 index.html,但有时候你不想叫这个名字,可以改。
filename:'youIndex.html'
minify压缩 去空格
minify: {
collapseWhitespace: true,
},
这个可以把生成的 index.html 文件的内容的没用空格去掉,减少空间。
处理css
css-loader 分析css关系-合并一个css(import)
style-loader 把css挂载到head里面
mini-css-extract-plugin 把css抽取到单独文件
optimize-css-assets-webpack-plugin用于压缩css文件,它将在webpack构建期间搜索css资源,并将优化/最小化css
less less-loader 处理less文件
npm install css-loader style-loader mini-css-extract-plugin optimize-css-assets-webpack-plugin -D
index.js
import {header} from './header.js'
import './css/style.css'
import './css/style.less'
document.body.append(header);
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports={
optimization: {
minimizer: [ new OptimizeCSSAssetsPlugin({})],
},
mode:'production',
entry:'./src/index.js',
output:{
filename:'main.js',
path:__dirname+'/dist'
},
module:{
rules:[
{
test:/.css$/,
use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader']
},
{
test:/.less$/,
use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader','less-loader']
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'style.css',
}),
]
}
webpack-dev-server
webpack-dev-server 本地服务
clean-webpack-plugin 清理dist目录
安装
npm install clean-webpack-plugin webpack-dev-server -D
webapck.config.js添加如下设置
module.exports = {
devServer: {
host: 'localhost', //主机地址,默认是localhost
port: '8080', //端口号,默认8080
open: true, //自动打开页面
hot:true,//热更新
},
};
package.json中添加开发环境启动指令
{
"scripts": {
"dev": "webpack serve"
}
}
执行npm run dev,即可在开发环境下运行项目了
图片与文件处理
file-loader可以解析项目中的url引入(不仅限于css)使之指向正确的文件
url-loader 会将小图片生成base64编码格式(url-loader封装了file-loader)
image-webpack-loader 插件可将大的图片进行压缩从而缩小打包体积
html-loader html 代码里处理 img 标签的 loader。
style.css
@import '../assets/font/iconfont.css';
div{ color:red;}
body{ background-image: url('../assets/sun.jpg');}
index.js
import {header} from './header.js'
import './css/style.css'
import './css/style.less'
import pic from './assets/pic1.jpg'
document.body.append(header);
var img = new Image();
img.src=pic;
// img.src=pic;
document.body.append(img);
var box = document.createElement("div");
box.innerHTML='<span class="iconfont icon-shouye1"></span> <span class="iconfont icon-shouye"></span>';
document.body.append(box);
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
devServer: {
contentBase: './dist',
},
optimization: {
minimizer: [ new OptimizeCSSAssetsPlugin({})],
},
// mode:'production',
entry:'./src/index.js',
output:{
filename:'main-[hash].js',
path:__dirname+'/dist'
},
module:{
rules:[
{
test: /.(png|jpg|gif|jpeg|ico)$/,
use:[{loader:'url-loader',options:{limit:50000,name: 'img/[name].[hash:5].[ext]'},'image-webpack-loader']
},
{
test:/.css$/,
use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader']
},
{
test:/.(eot|woff2|woff|ttf|svg)/,
use:[{loader:'url-loader',options:{limit:10,name: 'font/[name].[hash:5].[ext]'}}],
},
{
test:/.less$/,
use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader','less-loader']
}
]
},
plugins:[
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template:'./src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'style.css',
}),
]
}
设置目录别名
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, './src'), //设置@为src目录的别名
}
},
};
public公共静态资源目录拷贝
npm install --save-dev copy-webpack-plugin
webpack.config.js添加如下配置
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyWebpackPlugin( // 设置静态目录(拷贝文件到另外一个文件夹)
{patterns:[
// { from: __dirname+'/public', to: __dirname+'/dist' },
//from 从, to 到 __dirname 当前目录
{ from: __dirname+'/../src/static', to: __dirname+'/dist/static' },
],
}
),
],
};
参数说明
rom 定义要拷贝的源文件 from:__dirname+'/public'
to 定义要拷贝到的目标文件夹 to: __dirname+'/dist/public'
toType file 或者 dir 可选,默认是文件
force 强制覆盖前面的文件 可选,默认是文件
context 可选,默认base context可用specific context
flatten 只拷贝指定的文件 可以用模糊匹配
ignore 忽略拷贝指定的文件 可以模糊匹配
压缩
optimize-css-assets-webpack-plugin css优化压缩
const TerserPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
minimizer: [
new optimizeCssAssetsWebpackPlugin({}),
new TerserPlugin()
],
代码分割
optimization: {
splitChunks: {
chunks: "all",
// 所有的 chunks 代码公共的部分分离出来成为一个单独的文件},
},
sourceMap
当错误了,能够知道源代码在那一行 sourceMap 他是一个map关系,他知道dist/main。就是文件96行错误,对应src目录下index.js第一行
devtool:'cheap-module-eval-source-map',
建议
// development:'cheap-module-eval-source-map'
// production:'cheap-module-source-map'
按需导入js
等需要的时候异步加载 js 需要安装 插件
cnpm install @babel/plugin-syntax-dynamic-import -D
配置 babelrc plugins
{
"presets": ["@babel/preset-env","@babel/preset-react"],
"plugins":["@babel/plugin-syntax-dynamic-import"]
}
在js使用
function getComponent(){
return import(/* webpackChunkName:"jquery" */'jquery').then(({default:$})=>{
return $;
})
}
getComponent().then($=>{
var el = $("<div>你好jquery</div>");
$("body").append(el);
el.click(()=>{
alert("你好");
})
})
Prefetch
Prefetch是告诉浏览器这是一个在未来可能使用到的资源。 浏览器通常会在空闲状态取得这些资源,在取得资源之后搁在HTTP缓存以便于实现将来的请求
import时增加一条魔法注释即可:
document.body.onclick=()=>getJq();
function getJq(){
import( /* webpackChunkName:"jquery", webpackPrefetch: true */ 'jquery').then(({default:$})=>{
$("div").click(()=>{
alert("你好");
})
})
}
html标签页也可以实现
<link href=css/category.f436a150.css rel=prefetch>
<link href=js/about.d1393457.js rel=prefetch>
综合案例
getJQ(){
import(/* webpackChunkName:"jquery",webpackPrefetch:true */"jquery")
.then(({default:$})=>{
alert($("body").text())
})
}
// 构造函数
render(){
return(<div onClick={this.getJQ}> 你好react 我喜欢你</div>)
}