项目描述
本项目 webpack 的基本使用。
webpack 官方:https://webpack.docschina.org/concepts/
Element-plus 官方:https://element-plus.sxtxhy.com/zh-CN/
Vue3 官方:https://cn.vuejs.org/
项目组成明细
每个步骤完成后重新执行 npm run dev 即可看到效果
1、webpack
打包工具
安装
npm install webpack --save-dev
package.json
配置 dev 命令
{"name": "test","version": "1.0.0","description": "","main": "index.js","scripts": {"dev": "npx webpack --config webpack.dev.js"},"keywords": [],"author": "","license": "ISC","devDependencies": {"webpack": "^5.98.0"}
}
入口文件 main.js
创建 src 文件夹,创建文件 main.js
const h1 = document.createElement('h1')
h1.innerHTML = '666'
document.body.appendChild(h1)console.log(h1)
console.log(process.env.NODE_ENV === 'development')
配置文件 webpack.dev.js
const path = require('path')module.exports = {mode: 'development', // 开发模式// 入口文件entry: {dev_index: './src/main.js' // 这个对象的键名会传递到下面的'[name].bundle.js'中的 name},// 输出文件output: {filename: '[name].bundle.js', // 输出文件名path: path.resolve(__dirname, 'dist') // 输出文件目录},devtool: 'inline-source-map' // 开启source-map
}
2、html-webpack-plugin
生成 html 文件
安装
npm install html-webpack-plugin --save-dev
package.json
{// ..."devDependencies": {"webpack": "^5.98.0","html-webpack-plugin": "^5.6.3"}
}
创建文件 index.html
src 下面创建文件 index.html
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title><%= htmlWebpackPlugin.options.title %></title></head><body><div id="app"></div></body>
</html>
webpack.dev.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {// ...plugins: [new HtmlWebpackPlugin({title: 'template5-dev', // 生成的HTML文件标题filename: 'index.html' // 生成的HTML文件名template: './src/index.html', // 不配置此项,默认生成index.html;配置此项传递自定义HTML文件// favicon: path.join(__dirname, './src/img/favicon.ico')})]
}
3、webpack-dev-server
启动一个本地服务器,并实时更新页面
安装
npm install webpack-dev-server --save-dev
package.json
dev 命令增加 serve
{// ..."scripts": {"dev": "npx webpack serve --config webpack.dev.js"},// ..."devDependencies": {"webpack": "^5.98.0","html-webpack-plugin": "^5.6.3","webpack-dev-server": "^5.2.0"}
}
webpack.dev.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {// ...devServer: {static: './dist', // 静态资源目录hot: true, // 开启模块热更新port: 8080, // 端口号open: true, // 自动打开浏览器watchFiles: ['./src/index.html'], // 监听文件变化(自动刷新页面)client: {logging: 'none' // 关闭客户端日志// logging: 'error', // 仅显示错误}}
}
4、style-loader、css-loader
处理 css 文件
安装
npm install style-loader css-loader --save-dev
package.json
{// ..."devDependencies": {"webpack": "^5.98.0","html-webpack-plugin": "^5.6.3","webpack-dev-server": "^5.2.0","style-loader": "^4.0.0","css-loader": "^7.1.2"}
}
main.js
src 下面创建 css 文件夹,里面创建 index.css
// ...
import './css/index.css'
webpack.dev.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {// ...module: {rules: [{test: /\.css$/i, // 匹配css文件use: ['style-loader', 'css-loader'] // 使用loader}]}
}
5、url-loader
处理图片、字体等静态资源
安装
npm install url-loader --save-dev
package.json
{// ..."devDependencies": {"webpack": "^5.98.0","html-webpack-plugin": "^5.6.3","webpack-dev-server": "^5.2.0","style-loader": "^4.0.0","css-loader": "^7.1.2","url-loader": "^4.1.1"}
}
main.js
src 下面创建 img 文件夹, 添加 favicon.ico 文件
// ...
import img from './img/favicon.ico'console.log(img)
document.body.appendChild(img)
webpack.dev.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {// ...module: {rules: [// ...{test: /\.(png|svg|jpg|jpeg|gif)$/i, // 匹配图片文件use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }], // 使用loadertype: 'javascript/auto' // 解决图片打包后路径问题}]}
}
6、terser-webpack-plugin
压缩代码,去掉注释与 console.log 等 [生产环境时配置]
安装
npm install terser-webpack-plugin --save-dev
package.json
增加 build 命令
{// ..."scripts": {"dev": "npx webpack serve --config webpack.dev.js","build": "npx webpack --config webpack.prod.js"},// ..."devDependencies": {"webpack": "^5.98.0","html-webpack-plugin": "^5.6.3","webpack-dev-server": "^5.2.0","style-loader": "^4.0.0","css-loader": "^7.1.2","url-loader": "^4.1.1","terser-webpack-plugin": "^5.3.14"}
}
创建文件 webpack.prod.js
生产环境配置文件
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')module.exports = {mode: 'production',entry: {index: './src/main.js'},output: {publicPath: './',filename: '[name].js',path: path.resolve(__dirname, 'dist'),clean: true},plugins: [new HtmlWebpackPlugin({title: 'template5',filename: 'index.html',template: './src/index.html',favicon: path.join(__dirname, './src/img/favicon.ico')})],module: {rules: [{test: /\.css$/i,use: ['style-loader', 'css-loader']},{test: /\.(png|svg|jpg|jpeg|gif)$/i,use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }],type: 'javascript/auto'}]},optimization: {minimizer: [new TerserPlugin({terserOptions: {compress: {drop_console: true // 移除所有 console.*},format: {comments: false // 移除所有注释}},extractComments: false // 禁止生成独立的注释文件})]}
}
7、vue-loader
处理 vue 文件
安装
npm install vue-loader --save-dev
安装 vue3
npm install vue
package.json
{// ..."dependencies": {"vue": "^3.5.13"},"devDependencies": {"webpack": "^5.98.0","html-webpack-plugin": "^5.6.3","webpack-dev-server": "^5.2.0","style-loader": "^4.0.0","css-loader": "^7.1.2","url-loader": "^4.1.1","terser-webpack-plugin": "^5.3.14","vue-loader": "^17.4.2"}
}
创建文件 App.vue
src 下面创建 App.vue
<template><header><h1>{{ test_name }}</h1></header><main></main><footer></footer>
</template><script setup>
import { ref } from 'vue'const test_name = ref('app.vue')
</script>
main.js
// ...
import { createApp } from 'vue'
import App from './App.vue'const app = createApp(App)
app.mount('#app')
webpack.dev.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')module.exports = {// ...plugins: [// ...new VueLoaderPlugin() // 添加VueLoaderPlugin],// ...module: {rules: [// ...{test: /\.vue$/,loader: 'vue-loader'}]}
}
7.1 不使用 vue-loader 加载 vue
不使用 vue-loader 插件,也可以使用 vue 的方法
此法打包后项目大些,编译速度慢些,正常不推荐
main.js
// ...
import { createApp } from 'vue'createApp({data() {return {msg: 'Hello Vue!'}}
}).mount('#app')
index.html
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title><%= htmlWebpackPlugin.options.title %></title></head><body><div id="app">{{ msg }}</div></body>
</html>
webpack.dev.js
打包生产时也要加上此配置
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {// ...resolve: {alias: {vue$: 'vue/dist/vue.esm-bundler.js' // 包含编译器的构建版本}}
}
8、全局加载 Element plus
全局加载打包后项目偏大,但配置简单
安装
npm install element-plus
package.json
{// ..."dependencies": {"vue": "^3.5.13","element-plus": "^2.9.6"}// ...
}
main.js
// ...
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'const app = createApp(App)app.use(ElementPlus, {locale: zhCn
})app.mount('#app')
8.1、按需加载 Element plus
按需加载打包后项目偏小,但配置复杂,并且需要安装插件
安装插件
安装旧版,因最新版默认导出 ESM 格式,不支持 CommonJS 格式
npm install unplugin-auto-import@0.16.1 unplugin-vue-components@0.25.1 --save-dev
main.js
无需配置,如之前已配置全局 Element plus,需去掉
// ...
import { createApp } from 'vue'
import App from './App.vue'const app = createApp(App)
app.mount('#app')
App.vue
使用方法,并配置国际化
<template><el-config-provider :locale="zhCn"><el-button type="primary" @click="testOpen('test')">test</el-button></el-config-provider>
</template><script setup>
import { ref } from 'vue'
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'const testOpen = (name) => {ElMessage('this is a message.')
}
</script>
webpack.dev.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')module.exports = {// ...plugins: [// ...AutoImport({resolvers: [ElementPlusResolver()]}),Components({resolvers: [ElementPlusResolver()]})]// ...
}
9、axios
请求 axios
安装
npm install axios
package.json
{// ..."dependencies": {"vue": "^3.5.13","element-plus": "^2.9.6","axios": "^1.8.4"}// ...
}
创建 api.js
在 src 目录下创建 api.js
import axios from 'axios'const api = axios.create({baseURL: 'http://localhost:9000',timeout: 60000,headers: { ['Content-Type']: 'application/x-www-form-urlencoded' }// withCredentials: true // 跨域请求时是否需要使用凭证(携带cookie)
})// 请求拦截器
api.interceptors.request.use((req) => {return req},(err) => {return Promise.reject(err)}
)// 响应拦截器
api.interceptors.response.use((res) => {return res.data},(err) => {return Promise.reject(err)}
)const { get, post, put, delete: del } = apiexport const testGet = (params) => {return get('/tianqiApi', { params })
}
App.vue
<template><!-- // ... -->
</template><script setup>
// ...import { testGet } from './api'const testApi = async () => {try {const res = await testGet()console.log(res)} catch (error) {console.log(error)}
}testApi()
</script>
完整配置 webpack.dev.js
开发配置
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')module.exports = {mode: 'development', // 开发模式// 入口文件entry: {dev_index: './src/main.js' // 这个对象的键名会传递到下面的'[name].bundle.js'中的 name},// 输出文件output: {filename: '[name].bundle.js', // 输出文件名path: path.resolve(__dirname, 'dist') // 输出文件目录},devtool: 'inline-source-map', // 开启source-mapdevServer: {static: './dist', // 静态资源目录hot: true, // 开启模块热更新port: 8080, // 端口号open: true, // 自动打开浏览器watchFiles: ['./src/index.html'], // 监听文件变化(自动刷新页面)client: {logging: 'none' // 关闭客户端日志// logging: 'error', // 仅显示错误}},plugins: [new HtmlWebpackPlugin({title: 'template5-dev', // 生成的HTML文件标题filename: 'index.html', // 生成的HTML文件名template: './src/index.html', // 不配置此项,默认生成index.html;配置此项传递自定义HTML文件favicon: path.join(__dirname, './src/img/favicon.ico')}),new VueLoaderPlugin(), // 添加VueLoaderPluginAutoImport({resolvers: [ElementPlusResolver()]}),Components({resolvers: [ElementPlusResolver()]})],module: {rules: [{test: /\.css$/i, // 匹配css文件use: ['style-loader', 'css-loader'] // 使用loader},{test: /\.(png|svg|jpg|jpeg|gif)$/i, // 匹配图片文件use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }], // 使用loadertype: 'javascript/auto' // 解决图片打包后路径问题},{test: /\.vue$/,loader: 'vue-loader'}]}
}
完整配置 webpack.prod.js
生产配置
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')module.exports = {mode: 'production', // 生产模式// 入口文件entry: {index: './src/main.js' // 这个对象的键名会传递到下面的'[name].bundle.js'中的 name},// 输出文件output: {publicPath: './', // 输出文件路径前缀filename: '[name].js', // 输出文件名path: path.resolve(__dirname, 'dist'), // 输出文件目录clean: true // 每次构建前清理dist目录},plugins: [new HtmlWebpackPlugin({title: 'template5', // 生成的HTML文件标题filename: 'index.html', // 生成的HTML文件名template: './src/index.html', // 不配置此项,默认生成index.html;配置此项传递自定义HTML文件favicon: path.join(__dirname, './src/img/favicon.ico')}),new VueLoaderPlugin(), // 添加VueLoaderPluginAutoImport({resolvers: [ElementPlusResolver()]}),Components({resolvers: [ElementPlusResolver()]})],module: {rules: [{test: /\.css$/i, // 匹配css文件use: ['style-loader', 'css-loader'] // 使用loader},{test: /\.(png|svg|jpg|jpeg|gif)$/i, // 匹配图片文件use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }], // 使用loadertype: 'javascript/auto' // 解决图片打包后路径问题},{test: /\.vue$/,loader: 'vue-loader'}]},optimization: {minimizer: [new TerserPlugin({terserOptions: {compress: {drop_console: true // 移除所有 console.*},format: {comments: false // 移除所有注释}},extractComments: false // 禁止生成独立的注释文件})]}
}
完整配置 package.json
{"name": "template5","version": "1.0.0","description": "","main": "index.js","scripts": {"dev": "npx webpack serve --config webpack.dev.js","build": "npx webpack --config webpack.prod.js"},"keywords": [],"author": "","license": "ISC","dependencies": {"axios": "^1.8.4","element-plus": "^2.9.6","vue": "^3.5.13"},"devDependencies": {"webpack": "^5.98.0","html-webpack-plugin": "^5.6.3","webpack-dev-server": "^5.2.0","style-loader": "^4.0.0","css-loader": "^7.1.2","url-loader": "^4.1.1","vue-loader": "^17.4.2","terser-webpack-plugin": "^5.3.14","unplugin-auto-import": "^0.16.1","unplugin-vue-components": "^0.25.1"}
}
完整目录结构
src
|- img
| |- favicon.ico
|- css
| |- index.css
|- api.js // api文件
|- main.js // 入口文件
|- index.html // html文件
|- App.vue // vue文件
package.json
webpack.dev.js
webpack.prod.js