首页 > 其他分享 >webpack5 从零搭建 vue3 项目

webpack5 从零搭建 vue3 项目

时间:2025-01-16 22:34:26浏览次数:1  
标签:webpack5 vue const loader webpack vue3 test js 搭建

目前 vue3 官网推荐的工具链已经是 vite 了,就算是要使用 webpack 甚至是 webpack5,也可以直接使用 vue-cli。然而之所以写这个,可以当是 webpack5 的一个学习文章。同时也是因为之前有个项目是在 vue3 刚出来的时候使用 vue-cli (那是官网还是推荐使用 webpack,以及但是得版本为 webpack4)开发的,手动改成 webpack5,想记录下。

Webpack

是什么

本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

这个话是官网的原话,官网地址:webpack 中文

核心内容

  • Entry
  • Output
  • Loader

其作用是让 webpack 处理那些非 js, json 文件。由于 webpack 自身只能试别 js, json,其他后缀的文件需要经过 loader 处理,将他们转化成有效模块。loader 可以是同步的,也可以是异步的,支持链式调用。

  • Plugins

loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务:打包优化,资源管理,注入环境变量。plugin 会运行在 webpack 的不同阶段,贯穿整个编译周期,目的在于解决 loader 无法实现的其他事。

  • Module

vue3 项目搭建

首先创建项目名称,以及下载相关的库。

# 创建项目
mkdir webpack-vue3
cd webpack-vue3
# 初始化 npm
npm init -y
# 下载 webpack
npm install webpack webpack-cli webpack-dev-server -D
# 下载 vue
npm install vue
# 下载 css 相关 loader
npm install css-loader style-loader vue-loader postcss-loader postcss autoprefixer -D
# 下载 vue 相关
npm install vue-loader @vue/compiler-sfc -D
# 下载 babel 相关
npm install babel-loader @babel/core @babel/preset-env -D
# 下载 plugin
npm install html-webpack-plugin -D

首先根目录创建 srcpublic文件夹,文件夹内容如下所示:

<!-- public > 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 > main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')
<!-- src > App.vue -->
<template>
	<div class="container">
    <p>Vue3 Project</p>
    <p class="text">count: {{ count }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(1)
</script>

<style>
  .text {
    color: blue;
  }
</style>

初始化 vue 单页面程序后,下面开始配置 webpack,在根目录下创建 webpack.config.js 文件。

// . > webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
    mode: 'development',
    entry: './src/main.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
        clean: true
    },
    devtool: 'source-map',
    devServer: {
        static: './dist',
        hot: true
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            postcssOptions: {
                                plugins: [
                                    require('autoprefixer'), // 使用 autoprefixer 插件
                                ]
                            }
                        }
                    }
                ]
            },
          	{
                test: /\.(png|jpg|gif|svg|jpeg)$/,
                type: 'asset/resource', 			// 使用 asset/resource 类型
                generator: {
                    filename: 'public/images/[name].[contenthash:8][ext]', 	// 输出目录和文件名格式
                },
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
        new HtmlWebpackPlugin({
            template: './public/index.html'
        })
    ],
    resolve: {
        alias: {
            vue: 'vue/dist/vue.esm-bundler.js'
        },
        extensions: ['.js', '.vue', '.json']
    }
}

然后 package.json 配置脚本

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "server": "webpack server",
    "build": "webpack"
  },

完成到这一步,我们就可以在终端运行 npm run server 来跑起项目,也可以通过 npm run build 打包项目。这个只是一个简单的 webpack 配置,运行环境 mode 在正式打包的时候还要手动修改成 production,以及 source-map 移除等。对于要正式上线的项目,这样的配置往往是不够的。

优化 webpack 配置

拆分配置,配置运行环境

首先,我们先对项目进行环境的划分。

npm install cross-env -D

下载 cross-env 库,用于设置环境变量。下载完后,修改 package.json

{
    "scripts": {
    	"test": "echo \"Error: no test specified\" && exit 1",
    	"server": "webpack server --config build/webpack.dev.js",
    	"build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.js",
    	"build:test": "cross-env NODE_ENV=test webpack --config build/webpack.prod.js"
  	},
}

--config 后面是指定的配置文件,这个我们待会创建。build 这个指令是用来打包正式上线的,build:test 这个是用来测试打包效果的,用来展示打包量化工具等。这个你也可以用来用作 测试服的打包。就比如有些公司会分内测,外测以及正式服。你就可以不写 build:test,直接用 innerouterformal 代替。

然后就是创建对应的配置文件了。根据上面的路径,在根目录创建 build 文件夹,里面创建 webpack.common.jswebpack.dev.jswebpack.prod.js 三个文件。

// build > webpack.common.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
    entry: path.resolve(__dirname, '../src/main.js'),
    output: {
        filename: 'public/js/bundle.js',
        path: path.resolve(__dirname, '../dist'),
        clean: true
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader', 'postcss-loader']
            },
          	{
                test: /\.(png|jpg|gif|svg|jpeg)$/,
                type: 'asset/resource', 			// 使用 asset/resource 类型
                generator: {
                    filename: 'public/images/[name].[contenthash:8][ext]', 	// 输出目录和文件名格式
                },
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, '../public/index.html')
        }),
    ],
    resolve: {
        alias: {
            '@': path.resolve(__dirname, '../src'),
            vue: 'vue/dist/vue.esm-bundler.js',
        },
        extensions: ['.js', '.vue', '.json']
    }
}

webpack.common.js 中的配置和 webpack.config.js 中的大体一致,移除了 devtooldevServer 的配置,其他的也只是写小修改,例如 output 的时候输出位置以及添加了@ 别名。babel-loaderpostcss-loader 的配置也提取出去了,这里要在根目录下创建 .babelrcpostcss.config.js

// . > babelrc
{
  "presets": ["@babel/preset-env"]
}
// . > postcss.config.js
module.exports = {
    plugins: [
      require('autoprefixer')
    ]
}

接下来就是 webpack.dev.js

// build > webpack.dev.js
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')

module.exports = merge(commonConfig, {
    mode: 'development',
    devtool: 'source-map',
    devServer: {
        static: '../dist',
        hot: true,
        open: true
    },
})

dev 配置就是 devtool 以及 devServer 了,然后通过 webpack-mergecommondev 合并起来。

// build > webpack.prod.js
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')

module.exports = merge(commonConfig, {
  	mode: 'production'
})

prod 当前来看则是这样,相对简单。

添加 sass 预处理器

npm install sass sass-loader -D

然后在 webpack.common.jsmodule.rules 中添加 scss 的规则

// build > webpack.common.js
moudle.exports = {
  // ...
  module: {
    rules: {
      //...
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
      }
    }
  }
}

然后 .vue 中就能使用 lang="scss" 以及引入 .scss 文件。

拆分 chunk

拆分之前,我们先安装一下 webpack-bundle-analyzer,它是一个用于分析 Webpack 打包结果的工具。它可以生成一个可视化的报告,帮助开发者理解各个模块的大小以及它们在最终打包文件中的占比。

npm i -D webpack-bundle-analyzer

然后我们在 webpack.prod.js 中配置一下,这里要用到我们前面做的环境区分。我们只在 build:test 的时候才使用 webpack-bundle-analyzer

// build > webpack.prod.js
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')

const ENV = process.env.NODE_ENV
console.log('运行环境:' + ENV)

function getPlugins() {
	const plugins = []

	if (ENV === 'test') {
        plugins.push(new BundleAnalyzerPlugin({
            analyzerMode: 'static', // 生成静态报告
            openAnalyzer: true,
        }))
    }

	return plugins
}

module.exports = merge(commonConfig, {
  	mode: 'production',
	plugins: getPlugins()
})

这时候我们执行 npm run build:test 就可以看到打包出的 bundle.js 大小以及分布图。

接下来就是对 chunk 拆分了

通过 optimization.splitChunks 来进行拆分

// build > webpack.prod.js
module.exports = merge(commonConfig, {
  mode: 'production',
	plugins: getPlugins(),
    optimization: {
        splitChunks: {
            cacheGroups: {
                defaultVendors: {
                    name: 'vendor',
                    test: /[\\/]node_modules[\\/]/,
                    priority: 1,
                    chunks: 'all',
                    minChunks: 1,
                    minSize: 0
                },
                common: {
                    name: 'common',
                    minChunks: 2,
                    priority: 0,
                    chunks: 'all',
                    reuseExistingChunk: true,
                    minChunks: 2,
                    minSize: 0
                }
            }
        }
    },
})

配置完这个后,如果你直接执行 build 测试的话,会报错。因为这里你 output 的配置中的 filename 是定死的文件名。这里需要修改一下 webpack.common.js 中的配置。

// build > webpack.common.js
module.exports = {
    entry: path.resolve(__dirname, '../src/main.js'),
    output: {
      	// 修改部分
        filename: 'public/js/[name].[contenthash:8].js',
        path: path.resolve(__dirname, '../dist'),
        clean: true
    },
  
 		// ... 其他配置
}

这时在进行 npm run build:test ,就可以发现会打包出两个 js 文件。同时可以看到解析图也发生了改变。

对于某个路由的拆分

路由的拆分比较简单,只需要动态引入组件的时候使用 webpackChunkName

首先实现路由环境。

npm i vue-router

然后在 src 下创建 routersviews 文件夹。一个用来存路由配置,一个用来存具体的路由组件。

// src > routers > index.js
import { createWebHashHistory, createRouter } from "vue-router"

const Home = () => import(/* webpackChunkName: "home" */ '@/views/home/index.vue')
const Detail = () => import(/* webpackChunkName: "detail" */ '@/views/detail/index.vue')

const routes = [
    {
        path: '/',
        component: Home
    },
    {
        path: '/detail',
        component: Detail
    }
]

const router = createRouter({
    history: createWebHashHistory(),
    routes
})

export default router

// src > main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from "./routers"

const app = createApp(App)
app.use(router).mount('#app')
<!-- src > views > detail > index.vue -->
<template>
    <div class="detail-container">
        detail
        {{ count }}
    </div>
</template>

<script setup>
const count = ref(1)
</script>

<style lang="scss">
.detail-container {
    color: yellow;
}
</style>

<!-- src > views > home > index.vue -->
<template>
    <div class="main-container">
        home
        {{ count }}
    </div>
</template>

<script setup>
const count = ref(1)
</script>

<style lang="scss">
.main-container {
    color: blue;
}
</style>

<!-- src > App.vue -->
<template>
    <div class="container">
        <p>Vue3 Project</p>
        <p class="text">count: {{ count }}</p>
				<!-- 新增部分 -->
        <RouterView></RouterView>
    </div>
</template>

<script setup>
// 新增部分
import { RouterView } from 'vue-router'
import { ref } from 'vue'
const count = ref(1)
</script>

<style lang="scss">
.container {
    .text {
        color: blue;
    }
}
</style>

运行 build:test 会发现,这时候会多出 detail.[base:8]home.[base:8]。即说明拆分成功了。

提取 css

目前我们打包出来的都是 js 文件,样式也是在 js 文件中的。这里我们需要 mini-css-extract-plugin 库来将 css 样式从 javascrip 中提取出来。

npm install mini-css-extract-plugin -D

配置如下

// build > webpack.common.js
// ... 其他已有引用
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
 		module: {
     		rules: [
      	// ... 其他loader
      	// 修改部分
      	{
            test: /\.css$/,
            use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
        },
        {
            test: /\.scss$/,
            use: [
                MiniCssExtractPlugin.loader,
                'css-loader',
                'postcss-loader',
                'sass-loader'
            ]
        },
        ]
    },
  	plugins: [
      	// ... 其他 plugins
      	new MiniCssExtractPlugin({
            filename: 'public/css/[name].[contenthash:8].css'
        }),
    ]
}

配置完成后打包,就会生成对应的 css 文件。

添加缓存

webpack5 自己提供了 cache 功能

// build > webpack.prod.js
module.exports = {
  	cache: {
      	type: 'filesystem'
    }
}

打包后在 node_modules 中可以看到 .cache 文件夹。

其他配置

利用 progress-bar-webpack-plugin 库,显示打包进度。

// build > webpack.prod.js
// ... 其他引入
const ProgressBarPlugin = require('progress-bar-webpack-plugin')

function getPlugins() {
    const plugins = [
        new ProgressBarPlugin({
            format: `  :msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`
        })
    ]

    if (ENV === 'test') {
        // ... test 配置
    }

    return plugins
}

同时可以关闭自带的显示信息

module.exports = {
  	// ...
  	stats: {
        // 显示详细信息
        all: false,
        assets: true, // 显示打包的文件
        timings: true, // 显示构建时间
        modules: false,
        chunks: false,
        version: true, // 显示 Webpack 版本
        errors: true, // 显示错误
    },
}

最终打包的时候可以看到具体进度以及耗时。

标签:webpack5,vue,const,loader,webpack,vue3,test,js,搭建
From: https://www.cnblogs.com/limoonrise/p/18675858

相关文章

  • 信奥OJ的搭建
    第一步,服务器申请选择一:免费云服务器,免费虚拟主机如:阿贝云阿贝云提供了免费的云服务器和免费的云虚拟主机,可根据自己的实际应用情况选择。首先注册一个账户,然后需要支付0.3元做一个实名认证,如果实名认证成功了大概率会开通成功。如果......
  • Vue3在线聊天室
    更多开源项目请关注我的gitee:乌鸦像写字台(关注公众号:寻川的AI工具库免费得毕设必备软件以及详细项目运行文档)(he-haoran-hhh)-Gitee.com在Layout.vue中添加菜单选项<el-menu-itemindex="/home">首页</el-menu-item><el-menu-itemindex="/im">天农聊天室</el-menu-item......
  • 基SpringBoot+Vue3的游乐园管理系统
    文章目录详细视频演示项目介绍技术介绍功能介绍核心代码系统效果图详细视频演示文章底部名片,获取项目的完整演示视频,免费解答技术疑问项目介绍  游乐园作为娱乐休闲的重要场所,其管理效率和服务质量直接影响到游客的满意度和游乐园的声誉。传统的游乐园管理方式......
  • 使用docsify搭建github pages页面
    目录初始化相关配置index.htmlreadme.md_sidebar.mddocsify可以快速帮你生成文档网站。不同于GitBook、Hexo的地方是它不会生成静态的.html文件,所有转换工作都是在运行时。如果你想要开始使用它,只需要创建一个index.html就可以开始编写文档并直接部署在GitHubPages。......
  • vue3 实现标签拖拽排序 + curd
    ......
  • 【python入门】2.安装搭建python环境
    1.安装python解析器1.1为什么要装python解析器?python属于高级语言,计算机并不认识我们需要用解析器,将python文件,经过python解析器翻译成,计算机能够识别的机器语言1.2如何安装下载地址:PythonReleasePython3.7.9|Python.org检验安装完成在cmd中输入python,若出......
  • ubuntu下搭建Gitea代码托管平台
    在Ubuntu上部署Gitea是设置本地代码托管平台的简洁和高效选择。以下是详细步骤:步骤1:更新系统sudoaptupdate&&sudoaptupgrade-y步骤2:安装依赖sudoaptinstallgitsqlite3curl-yGitea支持多种数据库,默认使用SQLite。如果需要MySQL或PostgreSQL,可以先安......
  • vue3.0 keep-alive 缓存指定页面
    vue3.0keep-alive缓存指定页面**vue2.0和vue3.0keep-alive写法是有区别,不要太过于依赖AI**!!!!vue2的写法(不适用于vue3)<keep-alive><router-viewv-if="$route.meta.keepAlive"></router-view></keep-alive><router-viewv-if="!$route.met......
  • idea创建项目的搭建方式
    1.普通Java项目2.普通javaweb项目3.maven的javaweb项目4.maven的Java项目5.springboot项目(5种方式)......
  • vue3路由跳转页面不回顶部问题
    因为vue-router的跳转默认是保持原先的滚动位置,并不会自动回滚到顶部,所以需要在createRouter的时候配置一下。不废话~constrouter=createRouter({//history:createWebHistory(),history:createWebHashHistory(),routes,scrollBehavior(to,from,savedPosition......