webpack搭建VUE项目 ----- 更好的配置webpack
在之前的文章中,我们用简单的webpack来搭建了一个react项目,但我们可以很明显的发现仅仅是那样是不够开发用的,今天我将我在开发中的webpack配置分享,并解析其中的含义,之后我会把代码上传到我的GitHub上,欢迎大家下载。
开始搭建一个vue项目。
按照惯例,先介绍一下按照我的步骤完成后出现的文件结构。

一、依然是在vue-cli目录下的命令行输入 npm init -y 生成package.json。
二、创建webpack.base.js 和 webpack.dev.js
这里解释一下为什么不用webpack.config.js 而分成这两个:
1、base文件可以复用。
2、更清楚的文件结构。
后面会简称它们为 base.js,dev.js。
三、安装相关配置项
命令行输入:
npm i webpack wepack-cli webpack-dev-server vue-loader vue-template-compiler style-loader css-loader portfinder url-loader webpack-merge html-webpack-plugin -D 这里贴上所使用的包的版本号 "css-loader": "^4.2.2", "html-webpack-plugin": "^4.3.0", "portfinder": "^1.0.28", "style-loader": "^1.2.1", "url-loader": "^4.1.0", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "webpack": "^4.44.1", "webpack-cli": "^3.3.12", "webpack-dev-server": "^3.11.0", "webpack-merge": "^5.1.2"
我会在配置中遇到时解释它们。
四、配置base.js
首先,我们来看一下base.js的文件结构
const { join } = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const APP_PATH = join(__dirname, "src");
const BUILD_PATH = join(__dirname, "dist");
module.exports = {
entry: {},
output: {},
module: {},
resolve: {},
plugins: [],
};
如果看过我前面的文章的话,module.exports里的内容就不需要解释了,主要解释一下上面的那些
第一句:引用path里的join方法。
第二句:使用html-webpack-plugin,它的功能是简化了HTML文件的创建,以便为你的webpack包提供服务。
第三句: 使用vue-loader里的插件,这样在我们配置解析.vue的规则是才能使用vue-loader。
后面这两句是将src的路径和dist的路径赋予给这两个量。
这里的__dirname指是当前文件,也就是base.js文件的绝对路径。
首先,我们的entry里的代码:
entry: { index: join(__dirname, "src/index.js"), },
配置入口文件,不解释。
output:
output: { path: BUILD_PATH, filename: "bundle.js", },
配置出口文件,不解释。
module:
module: { rules: [ { test: /\.vue$/, exclude: /node_modules/, use: ["vue-loader"], }, { test: /\.css$/, exclude: /node_modules/, use: ["style-loader","css-loader"] }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: ['url-loader'], include: [ APP_PATH, ], }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, use: ['url-loader'], include: [ APP_PATH, ], }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: ['url-loader'], include: [ APP_PATH, ], }, ], },
第一个rule:解析.vue文件。
第二个rule:解析.css文件。
第三个rule:解析图片文件。
第四个rule:解析视频文件。
第五个rule:解析字体文件。
resolve:
resolve: { modules: ["node_modules"], extensions: ["less", ".js", ".vue"], alias: { "@": APP_PATH, // 为该路径配置别名。在项目中可以使用该别名代替该路径 }, },
配置文件名和路径名的别名和省略。
modules:引入模块可以简写。
extensions:省略扩展名的文件的扩展名查询,从后到前。
alias:路径的别名命名。
plugins:
plugins: [ new htmlWebpackPlugin({ template: "./index.html", }), new VueLoaderPlugin(), ],
第一个插件:配置静态HTML文件目录和一些HTML的配置项。
第二个插件:使vue-loader能够使用。
完整代码:
const { join } = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const APP_PATH = join(__dirname, "src"); // 把路径赋予,方便使用
const BUILD_PATH = join(__dirname, "dist");
module.exports = {
entry: {
index: join(__dirname, "src/index.js"),
},
output: {
path: BUILD_PATH,
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.vue$/,
exclude: /node_modules/,
use: ["vue-loader"],
},
{
test: /\.css$/, //处理css
exclude: /node_modules/,
use: [ "style-loader", "css-loader"],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: ['url-loader'],
include: [
APP_PATH,
],
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: ['url-loader'],
include: [
APP_PATH,
],
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: ['url-loader'],
include: [
APP_PATH,
],
},
],
},
resolve: {
modules: ["node_modules"],
extensions: ["less", ".js", ".vue"],
alias: {
"@": APP_PATH, // 为该路径配置别名。在项目中可以使用该别名代替该路径
},
},
plugins: [
new htmlWebpackPlugin({
template: "./index.html",
}),
new VueLoaderPlugin(),
],
};
五、配置dev.js
文件代码:
const webpack = require("webpack");
const { merge } = require("webpack-merge");
const portFinder = require('portfinder'); // 当端口被占用时,会让端口数+1,保证正常运行
const webpackNaseConfig=require('./webpack.base');
const webpackDevConfig =merge(webpackNaseConfig,{
mode:'development',
devtool:'#cheap-module-eval-source-map', // 改变调试过程和速度
context:__dirname, // 上下文 用于从配置中解析入口起点(entry point)和 loade
devServer:{
compress:true, // 是否启用gzip压缩文件
historyApiFallback:true, // 当找不到页面(404)时返回到首页
host:'localhost',
hot:true,
open:true,
quiet:true, // 将编译时候的信息只在第一次输出
overlay:{ // 浏览器中显示错误
warnings:true,
errors:true,
},
},
watchOptions:{ // 监听
ignored:[ // 不被监听项
/node_modules/,
],
},
plugins:[
new webpack.HotModuleReplacementPlugin(),
],
});
module.exports=portFinder.getPortPromise({
port:8080,
}).then((port)=>merge(webpackDevConfig,{
devServer:{
port,
},
}))
介绍几个没有说过的:
webpack-merge:将webpack配置项合并
portfinder:当端口被占用时,会让端口数+1,保证正常运行。
devtool:改变调试过程和速度。
context:上下文 用于从配置中解析入口起点(entry point)和 loade。
compress:是否启用gzip压缩文件。
historyApiFallback:当找不到页面(404)时返回到首页。
quiet: 将编译时候的信息只在第一次输出。
overlay: 浏览器中显示错误。
watchOptions:监听。
ignored:不被监听项。
最后的部分是portfinder的配置,意思是挂在8080端口,同时配置devServer的port项。
六、配置index.html
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body> </html>
跟之前的文章意义一样。
七、配置src下的index.js
首先先安装包:
npm i vue vue-router -S
代码:
import Vue from "vue"; import App from "@/App.vue"; import router from "@/router/index.js"; new Vue({ el: "#app", router, render: (h) => h(App), //vue在创建Vue实例时,通过调用render方法来渲染实例的DOM树,也就是这个组件渲染的是App的内容 //vue在调用render方法时,会传入一个createElement函数作为参数,也就是这里的h的实参是createElement函数,然后createElement会以App为参数进行调用 })
vue的东西,不在这里解释了。
八、配置App.vue
代码:
<template>
<div id="app">
hello world
<router-view />
</div>
</template>
<script>
export default {
name:'app'
}
</script>
<style scoped>
</style>
九、配置router的index.js
代码:
import Vue from "vue"; import vueRouter from "vue-router"; import hellow from "@/components/hellow.vue"; Vue.use(vueRouter); export default new vueRouter({ routes: [ { path: "/", component: hellow, }, ], });
vue的,不解释。
十、components的hellow
代码:
<template>
<div id="hellow">
HELLO WORLD
</div>
</template>
<script>
export default {
name:'hellow'
}
</script>
十一、package.json
代码(主要改这里):
"scripts": { "dev": "webpack-dev-server --config webpack.dev.js --progress --colors" },
至此,vue项目配置完成,为了使项目配置更加的合理化,便利化。引入一些插件
一、mini-css-extract-plugin
功能: 将CSS提取为独立的文件的插件,对每个包含css的js文件都会创建一个CSS文件
安装:
npm i mini-css-extract-plugin -D
使用:配置base.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 头部引入
{ // 修改rules中 CSS配置
test: /\.css$/, //处理css
exclude: /node_modules/,
use: [
{
loader : process.env.NODE_ENV === "production"? MiniCssExtractPlugin: "style-loader",
},
{
loader: "css-loader",
},
],
},
二、copy-webpack-plugin
功能:主要用于拷贝文件,常用来将静态文件(图片等)从开发环境拷贝到生产环境。
安装:
npm i copy-webpack-plugin -D
配置:base.js
const CopyWebpackPlugin = require("copy-webpack-plugin"); // 引入
// plugins 里的配置
new CopyWebpackPlugin({
patterns: [
{
from: `${APP_PATH}/assets/`,
to: `${BUILD_PATH}/assets/`,
},
],
}),
三、friendly-errors-webpack-plugin
功能:友好的错误提示插件。
安装:
npm i friendly-errors-webpack-plugin -D
配置:dev.js
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin'); // 引入
// plugins 里配置
new FriendlyErrorsPlugin(),
最后的base.js 代码
const { join } = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 将CSS提取为独立的文件的插件,对每个包含css的js文件都会创建一个CSS文件
const CopyWebpackPlugin = require("copy-webpack-plugin"); // 将一个文件拷贝到另一个文件
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const APP_PATH = join(__dirname, "src"); // 把路径赋予,方便使用
const BUILD_PATH = join(__dirname, "dist");
module.exports = {
entry: {
index: join(__dirname, "src/index.js"),
},
output: {
path: BUILD_PATH,
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.vue$/,
exclude: /node_modules/,
use: ["vue-loader"],
},
{
test: /\.css$/, //处理css
exclude: /node_modules/,
use: [
{
loader:
process.env.NODE_ENV === "production"
? MiniCssExtractPlugin
: "style-loader",
},
{
loader: "css-loader",
},
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: ['url-loader'],
include: [
APP_PATH,
],
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: ['url-loader'],
include: [
APP_PATH,
],
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: ['url-loader'],
include: [
APP_PATH,
],
},
],
},
resolve: {
modules: ["node_modules"],
extensions: ["less", ".js", ".vue"],
alias: {
"@": APP_PATH, // 为该路径配置别名。在项目中可以使用该别名代替该路径
},
},
plugins: [
new htmlWebpackPlugin({
template: "./index.html",
}),
new VueLoaderPlugin(),
new CopyWebpackPlugin({
patterns: [
{
from: `${APP_PATH}/assets/`,
to: `${BUILD_PATH}/assets/`,
},
],
}),
],
};
dev.js代码
const webpack = require("webpack");
const { merge } = require("webpack-merge");
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin'); // 友好的错误提示
const portFinder = require('portfinder'); // 当端口被占用时,会让端口数+1,保证正常运行
const webpackNaseConfig=require('./webpack.base');
const webpackDevConfig =merge(webpackNaseConfig,{
mode:'development',
devtool:'#cheap-module-eval-source-map', // 改变调试过程和速度
context:__dirname, // 上下文 用于从配置中解析入口起点(entry point)和 loade
devServer:{
compress:true, // 是否启用gzip压缩,压缩文件
historyApiFallback:true, // 当找不到页面时返回到首页
host:'localhost',
hot:true,
open:true,
quiet:true, // 将编译时候的信息只在第一次输出
overlay:{ // 浏览器中显示错误
warnings:true,
errors:true,
},
},
watchOptions:{ // 监听
ignored:[ // 不被监听项
/node_modules/,
],
},
plugins:[
new FriendlyErrorsPlugin(),
new webpack.HotModuleReplacementPlugin(),
],
});
module.exports=portFinder.getPortPromise({
port:8080,
}).then((port)=>merge(webpackDevConfig,{
devServer:{
port,
},
}))
至此,配置完成,如果哪里有问题,欢迎评论区提问和指正。

浙公网安备 33010602011771号