webpack是一个模块打包器(构建工具),它的主要目标是将JavaScript文件打包在一起,打包后的文件用于在浏览器使用,可以胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)
简言之就是:将生产环境中的部分代码(运行也依赖)打包进项目中,使其在运行环境可以直接运行
目前框架的脚手架几乎做到零配置,直接基于webpack再封装了一层
树结构:在一个入口文件中引入所有资源,形成所有依赖关系树状图
模块:模块可以是ES6模块,也可以是commonJS或者AMD模块,对于webpack来说,一个资源也是模块
chunk:打包过程中被操作的模块文件叫做chunk,例如异步加载一个模块就是一个chunk
bundle:bundle是最后打包后的文件,最终文件可以和chunk长得一模一样,大部分情况下他是多个chunk的集合,因此最终生产的bundle数量可能不等于chunk的数量
创建项目目录
初始化npm:npm init -y
安装webpack以及webpack-cli、webpack-dev-server:npm install webpack webpack-cli webpack-dev-server -D
创建src目录或根据需要创建下面的子目录
webpack --mode production
打包成运行模式
可以看到默认生成dist目录,js文件合并成main.js ctrl+alt+L
可以调整换行
webpack --mode development
打包成开发环境
可以直接将上述两条指令写进package.json,更方便运行打包命令
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
//...
}
运行 npm run dev
或 npm run build
即可执行打包命令
//webpack.config.js
//resolve用来拼接绝对路径的方法
const {resolve} = require('path')
module.exports = {
entry:'./src/index.js',
output: {
//输出文件名
filename:'[name].js',
path: resolve(__dirname,'build')
},
//loader 处理CSS image等
module:{
rules: [
]
},
//可以处理html资源
plugins: [
],
/*mode:"production" //development|| production 已经把这两种模式写进package.json中了*/
}
使用插件(plugins)对HTML文件进行处理(html-webpack-plugin)
使用步骤:
下载安装 npm i html-webpack-plugin -D
引入插件 const HtmlWebpackPlugin = require('html-webpack-plugin');
使用插件
plugins: [
//使用插件
new HtmlWebpackPlugin({
//要拿哪些打包,打包出的目录文件叫什么
template: "./src/index.html",
filename: "demo.html"
}),
],
自动打包到文件 demo.html
中,并引用了编译生成的资源(JS/CSS)
打包多个html
多个entry,每个html一个entry
新建多个HtmlWebpackPlugin
//多个entry
entry{
vendor: ['jquery','./src/js/common.js'],//通用js
index:"./src/js/index.js",
cart:"./src/js/cart.js"
},
//负责打包html文件,将js注入到html中,minify压缩html
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
chunks:["index","vendor"]
minify: {
collapseWhitespace:true,
removeComments:true
}
}),
new HtmlWebpackPlugin({
template: "./src/cart.html",
filename: "cart.html",
chunks:["cart","wendor"]
minify: {
collapseWhitespace:true,
removeComments:true
}
}),
],
js代码只要设置成生产模式(production)模式,会自动压缩
若想在开发环境下压缩HTML
plugins: [
//使用插件
new HtmlWebpackPlugin({
//要拿哪些打包,打包出的目录文件叫什么
template: "./src/index.html",
filename: "demo.html",
//压缩html代码
minify: {
//移除空格
collapseWhitespace:true,
//移除注释
removeComments:true
}
}),
],
下载后直接使用,不需要引用
npm i css-loader style-loader -D
下载css-loader处理css中的 @import
和 url
这样的外部资源
下载style-loader把样式插入到DOM中,方法是在head中插入一个style标签,并把样式写入到这个标签的innerHTML中
使用
//loader
module:{
rules: [
{test:/\.css$/, use:['style-loader','css-loader']}
]
},
css内容会打包在js文件中,可以使用插件提取成单独的CSS文件
下载插件 npm i mini-css-extract-plugin -D
在webpack.config.js中引入插件 const MiniCssExtractPlugin = require('mini-css-extract-plugin');
在plugin模块中使用插件
plugins:[new MiniCssExtractPlugin()]
,new MiniCssExtractPlugin({filename:'./css/demo.css'})
在CSS的rules中,使用MiniCssExtractPlugin.loader取代style-loader,提取js中Css内容为单文件
{test:/\.css$/, use:[MiniCssExtractPlugin.loader,'css-loader']}
{test:/\.css$/, use:[MiniCssExtractPlugin.loader,'css-loader','sass-loader']}
将SCSS或LESS打包(需要先转成CSS)
下载 npm i sass-loader less-loader - D
(-D表示开发环境)
规则中使用
module:{
rules:[
{test:/\.css$/, use:[MiniCssExtractPlugin.loader,'css-loader']},
{test:/\.scss$/, use:[MiniCssExtractPlugin.loader,'css-loader','sass-loader']},
{test:/\.less$/, use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']}
]
}
如果报错 cannot find module ‘sass’,需要安装 npm install node-sass
需要postcss处理,下载两个包 post-loader和postcss-preset-env
npm i postcss-loader postcss-preset-env -D
postcss会找到package.json中的browerslist里面的配置,通过配置加载css的兼容性修改loader的配置,新版需要写postcss.config.js,less和sass兼容性同理
{test:/\.css$/, use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']}
devServer给我们提供了开发过程中的服务器,是一个使用了express的Http服务器,它的作用主要是为了监听资源文件的变化,该http服务器和client使用了websocket通信协议,只要资源文件发生改变,webpack-dev-server就会实时地进行编译,不再需要我们每次改动后再次编译
npm install webpack-dev-server
target:'web'
在webpack.config.js文件中添加配置
devServer:{
contentBase: resolve(__dirname,'build'),
//启动gzip压缩
compress:true,
//设置服务器端口号
port:3000,
//自动打开浏览器
open:true
}