1. 新建项目
$ git clone https://gitee.com/Jennica824/okayDemo.git
$ cd okayDemo
// 初始化package.json
$ npm install y
$ npm install webpack webpack-cli --save-dev
// webpack 核心功能
// webpack-cli 命令行工具
2. package.json
2.1. 私有安装包
{
+ "private": true, // 确保安装包是私有的,
- // "main": "index.js", // 移除main入口,防止意外发布代码
}
2.2. dependencies
生产环境下,项目运行所需依赖,但是开发环境的依赖模块也可以配置到这里。
2.3. devDependencies
开发环境下,项目所需依赖。
2.4. 配置运行环境
// npm run start 开发运行
// npm run build 生产打包
"scripts": {
"build": "webpack --config ./config/webpack.prod.js",
"start": "webpack serve --config ./config/webpack.dev.js"
},
3. 配置
3.1 新建webpack文件夹
|-- webpack
| |-- webpack.common.js // 公用配置
| |-- webpack.dev.js // 开发时的配置
└ └── webpack.prod.js // 打包构建时的配置
3.2 webpack.common.js 中配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 根据模板文件生成html文件。
/**
* 配置信息中webpack的五大模块
* 1. mode:模式,通过选择production,development,none这三个值来告诉webpack使用相应的内置优化。
* 2. entry:设置入口文件。
* 3. output:打包出的文件存放处。
* 4. module.rules:loader(加载器),webpack本身只支持处理js,json文件,通过相应的loader将其他格式的文件进行处理,转换成有效的模块。
* 5. plugins:插件,loader用于处理不支持的类型的文件,而plugin则可以用于执行范围更广的任务。
*/
module.exports = (webpackEnv) => {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
return {
mode: webpackEnv,
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'asset/[name].[contenthash:8][ext][query]',
},
module: {
rules: [{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
{
// css兼容性处理
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
},
],
],
},
}
}
],
}, {
test: /\.(png|svg|jpg|jpeg|gif)$/,
type: 'asset',
generator: {
filename: 'image/[name].[contenthash:8][ext][query]'
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.ejs')
}),
],
};
};
* 3.3. webpack.common.js 中 pulgins 的html模板文件:index.html 文件
在根目录下新建 public/index.html 文件,用于生成html模版
<!-- public/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<title>Webpack5 demo</title>
</head>
<body>
<div id="root"> </div>
</body>
</html>
注意::这里如果用 .html 后缀的模板,html-webpack-plugin 始终无法正常的生成html,然后改为了 .ejs 后就正常了。
3.4 webpack.dev.js 中配置
const webpackCommonConfig = require('./webpack.common.js')('development');
module.exports = {
devServer: {
host: 'localhost', // 指定host,,改为0.0.0.0可以被外部访问
port: 8081, // 指定端口号
open: true, // 服务启动后自动打开默认浏览器
historyApiFallback: true, // 当找不到页面时,会返回index.html
hot: true, // 启用模块热替换HMR,在修改模块时不会重新加载整个页面,只会更新改变的内容
compress: true, // 启动GZip压缩
https: false, // 是否启用https协议
proxy: {
// 启用请求代理,可以解决前端跨域请求的问题
'/api': '[请求地址]:[端口号]',
},
},
...webpackCommonConfig,
};
3.5 webpack.prod.js 中配置
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin")
module.exports = merge(common, {
mode: 'production',
optimization: {
minimizer: [
// 压缩js
new TerserPlugin({}),
// 压缩css
new OptimizeCSSAssetsPlugin({}),
],
// 抽离代码
splitChunks: {
chunks: "all",
}
},
plugins: [
// 压缩 大于30K
new CompressionPlugin({
test: /\.(js|css)$/,
threshold: 30720,
})
]
});
4. 运行项目
4.1. 启动
$ npm start
http://localhost:8081/
4.2. 打包
$ npm run build
$ npm install --save-dev optimize-css-assets-webpack-plugin --legacy-peer-deps
5. 集成 VUE3
5.1 安装插件
要让 webpack 识别 .vue 文件,必须安装 vue-loader 插件。
$ npm install vue --save
$ npm install vue-loader --save-dev
注意:Vue2.x 时安装的是 vue-template-complier
vue-loader:解析和转换 .vue 文件,提取出其中的逻辑代码 <script>、样式代码 <style>、以及 HTML 模版 <template>,再分别把它们交给对应的 Loader 去处理。
5.2 在 webpack.common.js 中配置 webpack 识别 vue 文件
// webpack.common.js
module: {
rules: [{
test: /\.vue$/,
use: ['vue-loader']
}]
},
5.3. npm run dev 或 npm run build 报错,解决办法
删除
node-modules 文件夹和 package-lock.json 文件,然后重新 npm install
注意 解决办法:在根目录下新建
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader/dist/index');
module.exports = {
mode: 'development', // 环境模式
entry: path.resolve(__dirname, './src/main.js'), // 打包入口
output: {
path: path.resolve(__dirname, 'dist'), // 打包出口
filename: 'js/[name].js' // 打包完的静态资源文件名
},
plugins: [
// 每次打包,先把dist文件夹清空(必备)
new CleanWebpackPlugin,
// 添加 VueLoaderPlugin 插件
new VueLoaderPlugin,
// 解析为 html 模版
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/index.html'), // html模版地址
filename: 'index.html', // 打包后输出的文件夹名
title: 'webpack5搭建vue3项目'
})
],
module: {
rules: [
{ test: /\.vue$/, use: ['vue-loader'] },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
}
}
{
...
"scripts": {
"build": "NODE_ENV=production webpack --progress --config webpack.config.js",
"dev": "webpack serve --config webpack.config.js"
},
...
}
再次运行,问题解决,但是不能用 config 文件夹内的配置,具体什么原因,还没找到
5.4. router 配置 vue-router
1. 安装依赖
$ npm install vue-router@4 -S
2. 创建 home.vue 和 test.vue
<template>
<div>
首页
</div>
</template>
3. 创建 router.js 文件
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../src/views/home.vue';
import Test from '../src/views/test.vue'
const routerHistory = createWebHistory();
const router = createRouter({
history: routerHistory,
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/test',
name: 'Test',
component: Test
}
]
})
export default router;
4. 修改 main.js 文件
import { createApp } from 'vue'
import App from './App.vue'
+ import router from '../router/routre'
createApp(App)
+ .use(router)
.mount('#root')
5. 修改 app.vue
<template>
<div>
<router-view />
</div>
</template>
5.5. store 配置 VUEX / Pinia
1. 安装依赖 vuex4
$ npm install vuex@next --save
2. 创建 vuex 对应的 store/index.js
// src/store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
3. 安装依赖 Pinia
$ npm install pinia
4. Pinia 对应的 store/index.js
// main.ts
import { createPinia } from 'pinia'
app.use(createPinia())
// store/index.js
import { defineStore } from 'pinia'
export const todos = defineStore('todos', {
state: () => ({
/** @type {{ text: string, id: number, isFinished: boolean }[]} */
todos: [],
/** @type {'all' | 'finished' | 'unfinished'} */
filter: 'all',
// type 会自动推断为 number
nextId: 0,
}),
getters: {
finishedTodos(state) {
// 自动完成! ✨
return state.todos.filter((todo) => todo.isFinished)
},
unfinishedTodos(state) {
return state.todos.filter((todo) => !todo.isFinished)
},
/**
* @returns {{ text: string, id: number, isFinished: boolean }[]}
*/
filteredTodos(state) {
if (this.filter === 'finished') {
// 自动调用其他 getter ✨
return this.finishedTodos
} else if (this.filter === 'unfinished') {
return this.unfinishedTodos
}
return this.todos
},
},
actions: {
// 任何数量的参数,返回一个 Promise 或者不返回
addTodo(text) {
// 你可以直接改变状态
this.todos.push({ text, id: this.nextId++, isFinished: false })
},
},
})
[注意]:
Pinia和vuex不能同时存在。Pinia的具体使用,请转接下文 🔗
6. 配置核心功能
6.1. ES6+ 转 ES5
由于有些浏览器无法解析
ES6+等高级语法,需要将其转化为浏览器能解析的低级语法.
1. 安装依赖
$ npm install @babel/core babel-loader @babel/preset-env -D
* 踩坑
1. css解析处理
// 安装loader
$ npm install --save-dev style-loader css-loader --legacy-peer-deps
// package.json
devDependencies:{
"css-loader": "^6.7.1",
"style-loader": "^3.3.1",
}
// webpack/webpack.common.js
module: {
rules: [{
test: /\.css$/,
use: [ "style-loader", "css-loader" ]
}]
}