前言
手摸手教你如何打包,让你在动手的实践过程中感受 webpack。
在动手之前,你可先简单了解一下 webpack 的概念
每一小结都有对应的分支,方便大家学习
webpack 版本:5.58.1
入门
新建一个目录,初始化 npm
npm init
接下来安装webpack
和webpack-cli
两个包
npm i -D webpack webpack-cli
默认配置
新建一个文件夹src
,里面新建一个main.js
,写一点测试代码
console.log("webpack")
在 package.json 中 scripts 中添加新的命令
"scripts": {
"build": "webpack ./src/main.js"
},
复制代码
执行打包命令npm run build
此时如果生成了一个 dist 文件夹,并且内部含有 main.js 说明已经打包成功了
这个例子只是 webpack 自己默认的配置,下面我们要实现更加丰富的自定义配置
自定义配置
新建一个build
文件夹,里面新建一个webpack.config.js
const path = require('path');
module.exports = {
mode:'development', // 开发模式
entry: path.resolve(__dirname,'../src/main.js'), // 入口文件
output: {
filename: 'output.js', // 打包后的文件名称
path: path.resolve(__dirname,'../dist') // 打包后的目录
}
}
复制代码
更改打包命令
{
// ...
"scripts": {
"build": "webpack --config build/webpack.config.js"
},
}
复制代码
然后执行 npm run build
,会得到如下结果
其中 main.js 是我们第一次打包遗留的。
js 已经打包好了,接下来我们要做的就是将 js 引入到 html 文件中
添加 js 到 html 文件
我们需要 html-webpack-plugin 来帮我们完成这件事情
npm i -D html-webpack-plugin
新建一个与build
同级的文件夹public
,里面新建一个index.html
配置如下
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development', // 开发模式
entry: path.resolve(__dirname,'../src/main.js'), // 入口文件
output: {
filename: '[name].[hash:8].js', // [name] 指entry属性名字, 默认为main
path: path.resolve(__dirname,'../dist') // 打包后的目录
},
plugins:[
new HtmlWebpackPlugin({
// 选取一个html作为模版,在dist目录下会生成一个相同的html,之后将打包好的js注入到该html文件
template: path.resolve(__dirname,'../public/index.html')
})
]
}
复制代码
打包成功之后,查看 dist 目录下的 index.html 文件是否引用了打包之后的 js
多文件如何注入到 html
多个入口文件,注入到同一个 html 文件中
这种情形我们只需添加入口就 OK 了,html-webpack-plugin
插件会自动把所有打包好的 js 注入到 html 里
module.exports = {
// ...
entry: {
main: path.resolve(__dirname,'../src/main.js'),
share: path.resolve(__dirname,'../src/share.js')
}
}
复制代码
多个入口文件,根据不同需求注入到不同的 html 文件
我们可以通过生成多个 html-webpack-plugin 实例来解决这个问题
module.exports = {
// ...
plugins:[
new HtmlWebpackPlugin({
// 选取一个html作为模版,在dist目录下会生成一个相同的html,之后将打包好的js注入到该html文件
template: path.resolve(__dirname,'../public/index.html'),
filename: 'index.html',
chunks: ['main'] // 配置将哪些文件注入到该html文件,为[]在代表不注入js,若无该属性,默认注入所有js
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname,'../public/share.html'),
filename: 'share.html',
chunks: ['share']
})
]
}
复制代码
打包前清空 dist 目录
相信大家也发现了,dist 目录下的文件越来越多,下面我们就来解决这个问题
我们需要 clean-webpack-plugin 来帮我们完成这件事情
npm i -D clean-webpack-plugin
// 其余配置同上
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
plugins:[
// ...
new CleanWebpackPlugin()
]
}
复制代码
经掘友提醒,webpack5 有新增清空 dist 目录的方式,在 output 增加 clean 字段,现补充在下面
module.exports = {
// ...
output: {
filename: '[name].[hash:8].js', // [name] 指entry属性名字, 默认为main
path: path.resolve(__dirname,'../dist'), // 打包后的目录
clean: true
},
}
复制代码
将 css 以 style 标签的方式注入到 html
我们的入口文件是 js,所以我们在入口 js 中引入我们的 css 文件
// main.js
import "../static/css/base.css"
import "../static/css/color.scss"
import "../static/css/fontsize.less"
console.log("webpack")
复制代码
我们需要一些 loader 来解析我们的 css 文件
npm i -D style-loader css-loader
如果使用 less 来构建样式,则需要安装
npm i -D less less-loader
如果使用 scss 来构建样式,则需要安装
npm i -D node-sass sass-loader
配置文件如下
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"] // 从右向左开始解析
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"] // 此外还需要安装node-sass(sass也行)
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader'] // 此外还需要安装less模块
}
]
}
}
复制代码
打包之后在浏览器中打开 html 文件,就能看见我们注入的 css
为 css 添加浏览器前缀
为了适配更多的浏览器样式我们需要给 css 加上前缀
我们需要 postcss-loader 以及autoprefixer
来帮我们完成这件事情
参考 webpack 视频讲解:进入学习
引入autoprefixer
方式有两种
postcss.config.js
引入(推荐)
在**项目根目**
录下创建postcss.config.js
,配置如下
module.exports = {
plugins: [
require('autoprefixer')
]
}
复制代码
然后直接在webpack.config.js
中引入
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader", "postcss-loader"] // 从右向左开始解析
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"] // 此外还需要安装node-sass(sass也行)
},
{
test:/\.less$/,
use:['style-loader','css-loader', "postcss-loader", 'less-loader'] // 此外还需要安装less模块
}
]
}
}
复制代码
直接在webpack.config.js
配置
moudule.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader", {
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
['autoprefixer']
]
}
}
}] // 从右向左开始解析
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", {
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
['autoprefixer']
]
}
}
}, "sass-loader"] // 此外还需要安装node-sass(sass也行)
},
{
test:/\.less$/,
use:['style-loader','css-loader', {
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
['autoprefixer']
]
}
}
}, 'less-loader'] // 此外还需要安装less模块
}
]
}
}
复制代码
完成上述配置之后,我们发现 css 并未成功加上前缀。这里我们还要进行一步操作,那就是配置package.json
,在package.json
中添加如下配置
{
// ...
"browserslist": [
"defaults",
"not ie < 11",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]
}
复制代码
外链引入 css 文件
上述我们通过 style 标签的方式加载我们的样式,但如果 css 文件过多就显得很混乱。
我们需要 mini-css-extract-plugin 帮我们实现
npm i -D mini-css-extract-plugin
// 其余配置保持不变
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// ...
plugins: [
// ...
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
})
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"] // 从右向左开始解析
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", {
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
['autoprefixer']
]
}
}
}, "sass-loader"] // 此外还需要安装node-sass(sass也行)
},
{
test:/\.less$/,
use:[MiniCssExtractPlugin.loader,'css-loader', "postcss-loader", 'less-loader'] // 此外还需要安装less模块
}
]
}
}
复制代码
不过通过这种方式会将所有的 css 合并到一个 css 文件里,如果想要拆分就只有用其他办法里,网上看别人用的是extract-text-webpack-plugin
,不过当我去 npm 官网看时。
所以这里就先不讨论拆分 css 了
图片处理
css 与 js 中图片处理只需添加如下配置就行
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.(jpe?g|png|gif)$/i,
type: "asset",
generator: {
filename: 'static/[name].[hash].[ext]'
}
},
]
}
}
复制代码
如果需要处理 html 中的图片则需要用到 html-loader
npm i -D html-loader
配置如下
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.html$/i,
loader: "html-loader"
},
]
}
}
复制代码
如果需要配置更多的资源文件,请参考资源模块
转义 js 文件
为了使我们的 js 代码兼容更多的环境我们需要转义我们的 js 文件
npm i -D babel-loader @babel/preset-env @babel/core core-js
module.expors = {
// ...
module: {
rules: [
// ...
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {
//core-js的版本
version: 3
},
//需要兼容的浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
],
}
},
exclude: /node_modules/
}
]
}
}
复制代码
babel-loader
负责将 ES6/7/8 等语法转换为 ES5 语法
core-js
负责将新的 api 进行转化,例如 promise、Generator、Set、Maps、Proxy 等
进阶
搭建 Vue 开发环境
Vue 文件处理
首先安装必要依赖
npm i -D vue-loader vue-template-compiler vue-style-loader
npm i -S vue
vue-loader 用于解析.vue
文件
vue-template-compiler 用于编译模板
vue-style-loader 解析样式
const vueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
// ...
module:{
rules:[
// 这一个loader必须放在最前面
{
test:/\.vue$/,
use:['vue-loader']
}
// ...
]
},
resolve:{
// 设置路径别名
alias:{
'vue$':'vue/dist/vue.runtime.esm.js',
'@':path.resolve(__dirname,'../src')
},
// 尝试按顺序解析这些后缀名。
// 如果有多个文件有相同的名字,但后缀名不同,webpack 会解析列在数组首位的后缀的文件 并跳过其余的后缀。
extensions:['*','.js','.json','.vue']
},
plugins:[
new vueLoaderPlugin()
]
}
复制代码
热更新配置
我们需要使用 webpack-dev-server 来启动一个本地服务并且配置热更新
npm i -D webpack-dev-server
配置如下
const Webpack = require('webpack')
module.exports = {
// ...
devServer:{
port:3000,
hot:true
},
plugins:[
new Webpack.HotModuleReplacementPlugin()
]
}
复制代码
配置打包命令
"scripts": {
// ...
"dev": "webpack-dev-server --config build/webpack.config.js --open"
},
复制代码
添加 --open
可自动打开 http://localhost:3000
页面
接下来写几行代码进行测试,先修改我们的 main.js
// main.js
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
复制代码
新建一个 App.vue 文件
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default { data() { return { msg: "webpack vue"
} }}
</script>
<style lang='scss' scoped>
div { color: aquamarine; display: flex;}
</style>
复制代码
修改原来的 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>webpack</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
复制代码
最后执行npm run dev
区分开发环境和生产环境
development(开发环境) 和 **production(生产环境) **这两个环境下的构建目标存在着巨大差异。在开发环境中,我们需要:强大的 source map 和一个有着 live reloading(实时重新加载) 或 hot module replacement(热模块替换) 能力的 localhost server。而生产环境目标则转移至其他方面,关注点在于压缩 bundle、更轻量的 source map、资源优化等,通过这些优化方式改善加载时间。由于要遵循逻辑分离,我们通常建议为每个环境编写彼此独立的 webpack 配置。
我们在原来webpack.config.js
的基础上再新增两个文件webpack.prod.js
和webpack.dev.js
这里我们需要使用 webpack-merge 帮我们 merge 代码
npm i -D webpack-merge
// webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.config.js')
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer:{
port:3000,
hot:true
}
});
复制代码
// webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.config.js');
module.exports = merge(common, {
mode: 'production',
});
复制代码
原先的webpack.config.js
也需要做出修改,我们只需要删除mode
和devserver
字段就行了
最后修改package.json
中的scripts
命令
"scripts": {
"build": "webpack --config build/webpack.prod.js",
"dev": "webpack-dev-server --config build/webpack.dev.js --open"
},
复制代码
开发环境运行npm run dev
,打包npm run build
最后
码字不易,若是对你有帮助,那就点个赞吧
评论