1.初始化项目
先创建一个webpackDemo文件夹,切换进去执行如下命令,
npm install --save-dev webpack-cli@4.4.0
2.基本概念
1. 入口(entry) Webpack 执行构建的第一步将从 Entry 开始,可理解为输入。
2. 输出(output)输出结果,在 Webpack 经过一系列处理后输出的配置
3. loader (模块转换器)对文件类型选择对应的loader
4. 插件(plugins) 扩展插件,在 Webpack对文件处理的扩展处理
3.配置webpack.config.js
在项目根目录新建webpack.config.js,文件路径如下。
在package.json里面配置script:
"dev": "webpack --mode development",
"build": "webpack --mode production",
"start": "webpack-dev-server --mode development"
这样我们就可以在命令行使用 npm run dev这样的命令
添加入口文件路径和输出路径,服务器配置
module.exports = {
entry:{
index:"./src/index.js", //入口文件为/src/index.js
},
output:{
filename: 'bundle[hash].js', //[name]][hash].js,name可以设置,不设置就是默认命名如上面index就是路径的命名
path: path.resolve(__dirname, 'build') //设置输出文件夹跟webpack.config.js同一级
},
//热更新
devServer: {
contentBase: './build', //要放在服务器上的文件名
host:'localhost', //设置主机
port:8080, //设置端口
open: true, //设置浏览器自动打开
hotOnly: true, //只热更新,不刷新浏览器,后面说
},
}
在命令行输入npm run dev 输出结果:前面就是bundel,后面跟的hash值,
4.指定js loader,转译es6->es5
先安装babal-loader,等相关的依赖,有很多错误是安装的版本太高,不兼容,需要自己去npm下载对应的
低版本型号。大致的安装命令如下,具体的低版本型号需要自己指定。
npm install babel-loader babel-core babel-preset-env webpack
module:{
rules:[
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
]
},
exclude是只指不对符合条件的文件打包,
5.指定css loader
安装命令:npm install --save-dev css-loader
配置如下
{
test: /\.css$/,
use: [
"style-loader", "css-loader" ,
]
}
6.指定sass loader
安装命令:npm install sass-loader node-sass webpack --save-dev
{
//匹配以.scss结尾的文件
test: /\.scss$/,
//使用哪个加载器,这边顺序不能乱。
use: [
"style-loader", "css-loader" ,"sass-loader"
]
}
7.给css3添加浏览器前缀 postcss-loader
需要安装 npm i -D postcss-loader
//在package.json里面添加如下
"browserslist": [
"Firefox > 20",
"iOS >= 7",
"ie >= 8",
"last 5 versions",
"> 5%"
]
//webpack.config.js
{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
plugins: [
//添加自动加前缀插件
require("autoprefixer"),
],
},
},
],
},
7.对html处理 html-loader
{
test: /\.(html)$/,
use: {
loader:"html-loader",
options: {
//默认attrs=img:src,处理img的src属性,
attributes: true
}
}
}
8.对图片进行处理 file-loader
{
//支持的图片格式,处理css里面的链接的图片
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'file-loader',
options:{
esModule:false, //html-loader可以解析img的src图片
// name: ’[hash].[ext]‘,
name:'[hash].jpg',
//可用于cdn
// publicPath:'http://www.abc.com/img'
//设置输出文件夹
outputPath:'./img'
}
}
]
}
8.1对第三方库js处理 file-loader,
//引入webpack
const webpack = require("webpack");
//与module同一目录
resolve:{
//对文件取别名
alias: {
jQuery:path.resolve(__dirname,"../","src/jquery-3.6.0.min.js")
}
},
//在plugin里
new webpack.ProvidePlugin({
$:'jQuery'
}),
这样可以在js里面使用$符号
$(‘div’).addClass(‘myhead’);
9.生成一个 HTML5 文件插件 HtmlWebpackPlugin
在module.exports外部导入HtmlWebpackPlugin :
var HtmlWebpackPlugin = require("html-webpack-plugin");
plugins:[
new HtmlWebpackPlugin({
//要打包的文件
template: './index.html',
//打包好后输出的文件名
filename:'./webpack.html',
minify:{
collapseWhitespace: true,//去除空白
removeAttributeQuotes:true,//去除引号
removeComments: true, //去除注释
minifyCSS:true, //压缩html的css
minifyJS:true, //压缩html内的js
removeEmptyElements:true, //清楚内容为空的元素
},
hash:true //给打包的资源加上hash,避免缓存
}),
10.清除生成文件插件 CleanWebpackPlugin
当重新编译时,生成的新的js文件和旧的文件堆在一起,非常臃肿,我们希望之前的文件清除,只保留最新编译
的文件,CleanWebpackPlugin是最常见的插件
//module.exports外:
const CleanWebpackPlugin = require('clean-webpack-plugin');
//module.exports内:
new CleanWebpackPlugin('build'),
11.CSS文件分离成单独文件夹 MiniCssExtractPlugin
一般打包好的css文件都是在bundle.js中,因此如果需要将css单独放到css文件夹下就要使用MiniCssExtractPlugin插件
//module.exports外:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
//module.exports内:
//module内:
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
plugins: [
require("autoprefixer"),
],
},
},
],
},
//plugins内
plugins:[
//将所有的css文件都放在在 build/css/index.css 中
new MiniCssExtractPlugin({filename: "./css/index.css",}),
]
12.拷贝静态问价 CopyWebpackPlugin
//module.exports外面
const CopyPlugin = require("copy-webpack-plugin");
//module.exports里面
new CopyPlugin([
{
from: path.resolve(__dirname, "./src", "assets"),
to: path.resolve(__dirname, "./build", "assets")
}
],
),
13. 热模块更新插件 HotModuleReplacementPlugin
有时候我们想更换模块,但是又不想加载整个页面,就可以用到这个插件,还需要在devServer里面设置
hotOnly: true
const webpack = require("webpack");
devServer: {
contentBase: "./build", //要放在服务器上的文件名
host: "localhost", //设置主机
port: 8080, //设置端口
open: true, //设置浏览器自动打开
hotOnly: true, //只热更新,不刷新浏览器,后面说
},
plugins:[
new webpack.HotModuleReplacementPlugin()
]
对于js来说一定要加上下面这段代码才能生效
if(module.hot){
module.hot.accept();
}
13. 压缩css代码插件 CssMinimizerPlugin
//与module,plugins是同一层级
optimization: {
//If you want to run it also in development set the optimization.minimize option to true
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
//删除注释
discardComments: { removeAll: true },
},
],
},
}),
],
},
//如果想同时压缩css和scss结尾的文件,代码如下
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
plugins: [require("autoprefixer")],
},
},
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader",
{
loader: "postcss-loader",
options: {
plugins: [require("autoprefixer")],
},
},
],
},
最终结果如下:css压缩成一行,注释也移除。
13.webpack配置文件模块化
有些plugin和loader分别使用于生产环境和开发环境,有些是两则都需要,因此可以将配置文件抽离出
公共部分,developement和product部分。
上图是新建config文件夹,把各部分配置文件放在这里
生产环境;
1. 压缩代码
2. 不需要热更新
3. 提取css
4. 压缩css文件
5. sourceMap
6. 构建前清除上一次构建的内容
开发环境:
1. 不需要压缩代码
2. 需要热更新
3. css不需要提取到css文件
4. sourceMap
webpack.com.config.js
const path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
module.exports = {
//入口文件
entry: {
index: "./src/index.js",
},
//输出文件
output: {
filename: "bundle[hash].js",
path: path.resolve(__dirname, "../build"),
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
//css3添加浏览器前缀
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [[require("autoprefixer")]],
},
},
},
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader",
{
loader: "postcss-loader",
options: {
plugins: [require("autoprefixer")],
},
},
],
},
{
//图片格式
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: "file-loader",
options: {
esModule: false, //html-loader可以解析img的src图片
name: "[name]_[hash].[ext]",
//可以改变发布后的地址,可用于cdn
// publicPath:'http://www.abc.com/img'
//设置输出文件夹
outputPath: "./img",
},
},
],
},
{
//字体图标处理
test: /\.(ttf|woff|woff2)$/,
use: [
{
loader: "file-loader",
options: {
outputPath: "./font",
},
},
],
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
{
test: /\.(html)$/,
use: {
loader: "html-loader",
options: {
attributes: true,
},
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
//要打包的文件
template: "./index.html",
//打包好后的文件名
filename: "./webpack.html",
minify: {
collapseWhitespace: true, //去除空白
removeAttributeQuotes: true, //去除引号
removeComments: true, //去除注释
minifyCSS: true, //压缩html的css
minifyJS: true, //压缩html内的js
removeEmptyElements: true, //清楚内容为空的元素
},
hash: true, //给打包的资源加上hash,避免缓存
}),
new MiniCssExtractPlugin(),
//因为是在config下,所以要上一个层级路径
new CleanWebpackPlugin("build", {
root: path.resolve(__dirname, "../"),
}),
],
};
webpack.dev.config.js
const path = require('path');
let webpack = require('webpack');
let merge=require('webpack-merge');
let common =require('./webpack.com.config')
module.exports = merge(common,
{
//设置source maps,
devtool:'eval-cheap-module-source-map',
devServer: {
contentBase: './build',
host:'localhost',
port:8080,
open: true,
//只热更新,不刷新页面
hotOnly: true,
},
plugins:[
//热更新模块插件
new webpack.HotModuleReplacementPlugin()
],
})
webpack.prod.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
let merge = require("webpack-merge");
let common = require("./webpack.com.config");
module.exports = merge(common, {
devtool: "source-map",
plugins: [
//将css文件打包成一个单独的文件
new MiniCssExtractPlugin({
//要输出的css位置
filename: "./css/index.css",
}),
//复制拷贝插件
new CopyPlugin([
{
from: path.resolve(__dirname, "../src", "assets"),
to: path.resolve(__dirname, "../build", "assets"),
},
]),
],
//css优化压缩插件
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
//删除注释
discardComments: { removeAll: true },
},
],
},
}),
],
},
});
同时package.json里的脚本也要更改下
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development --config ./config/webpack.dev.config.js ",
"build": "webpack --mode production --config ./config/webpack.prod.config.js",
"start": "webpack-dev-server --mode development --config ./config/webpack.dev.config.js"