浅析Webpack5搭建vue3项目

关于项目的前置配置,请看以下两篇文章

浅析Webpack5搭建基本项目

浅析Webpack5搭建基本项目(优化)

那么接下来就开始配置Vue3了

首先将js和ts的loader改为babel配置,参考这里

之前的配置过于麻烦,所以统一由babel做了

先安装依赖

  • npm i -save-dev babel-loader @babel/core @babel/preset-env @babel/preset-typescript @babel/plugin-transform-runtime @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread
  • npm i --save @babel/runtime @babel/runtime-corejs3 [email protected]

然后在项目根目录配置文件babel.config.js

module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        useBuiltIns: "usage", // 按需引入 polyfill
        corejs: 3,
      },
    ],
    [
      "@babel/preset-typescript", // 引用Typescript插件
      {
        allExtensions: true, // 支持所有文件扩展名,否则在vue文件中使用ts会报错
      },
    ],
  ],
  plugins: [
    [
      "@babel/plugin-transform-runtime",
      {
        corejs: 3,
      },
    ],
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread",
  ],
};

之后在webpack配置这里修改

module.exports = {
    module : {
        rules : [
            {
                test: /\.(t|j)s$/,
                exclude: /node_modules/,
                use: [
                  {
                    loader: "babel-loader",
                  },
                ],
            }
        ]
    }
}

1.安装Vue3.x

  • npm i add vue@next
  • npm i vue-loader@next @vue/compiler-sfc -D
  • 创建src/index.js
  • 创建src/App.vue

webpack配置

const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
    module: {
        rules: [{
                test: /.vue$/,
                use: 'vue-loader'
        }]
    },
    plugins: [
        new VueLoaderPlugin()
    ],
}

src/index.js代码

import { createApp } from "vue";
import App from "./App.vue";
let app = createApp(App);
app.mount("#app");

src/App.vue代码

<template>
  <div class="app">
    我是根组件
  </div>
</template>

<script setup lang="ts"></script>

<style></style>

2.安装Vue Router

  • npm i vue-router@next
  • 创建 src/router/index.js
  • 创建 src/views文件夹
  • 创建 src/views/About.vue
  • 创建 src/views/Home.vue

src/index.js代码

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
let app = createApp(App);
app.use(router)
app.mount("#app");

src/views/About.vue代码

<template>
  <div class="about">about</div>
</template>

<script setup lang="ts"></script>

<style></style>

src/views/Home.vue代码

<template>
  <div class="home">home</div>
</template>

<script setup lang="ts"></script>

<style></style>

src/router/index.js代码

import { createRouter, createWebHashHistory } from "vue-router";

const routes = [
  {
    path: "/",
    name: "Home",
    component: () => import("@/views/Home.vue"),
  },
  {
    path: "/about",
    name: "About",
    component: () => import("@/views/About.vue"),
  },
];

export default createRouter({
  history: createWebHashHistory(),
  routes,
});

src/App.vue代码

<template>
  <div class="app">
    <router-link to="/">home</router-link>
    <router-link to="/about">home</router-link>
    <router-view></router-view>
  </div>
</template>

<script setup lang="ts"></script>

<style></style>

3.安装Vuex(二选一)

  • npm i add vuex@next
  • 创建 src/store/index.js

src/store/index.js代码

import { createStore } from "vuex";

export default createStore({
  state: { count: 1 },
  getters: {
    getCount(state) {
      return state.count;
    },
  },
  mutations: {
    updateCount(state, val) {
      state.count = val;
    },
  },
  actions: {
    asyncUpdateCount(store, val) {
      setTimeout(() => {
        store.commit("updateCount", val);
      }, 1000);
    },
  },
  modules: {},
});

src/index.js代码

import { createApp } from "vue";
import App from "./App.vue";
import store from "./store";
import router from "./router";

let app = createApp(App);
app.use(store).use(router);

app.mount("#app");

src/App.vue代码

<template>
  <div class="app">
    <router-link to="/">home</router-link>
    <router-link to="/about">home</router-link>
    <div>当前count的值为{{ getState }}</div>
    <button @click="updateCount">同步更新</button>
    <button @click="asyncUpdateCount">异步更新</button>
    <router-view></router-view>
  </div>
</template>

<script setup lang="ts">
import { computed } from "vue";
import { useStore } from "vuex";
const store = useStore();
let getState = computed(() => {
  return store.getters.getCount;
});

let updateCount = () => {
  store.commit("updateCount", getState.value + 1);
};

let asyncUpdateCount = () => {
  store.dispatch("asyncUpdateCount", getState.value + 1);
};
</script>

<style></style>

4.安装Pinia(二选一)

  • npm i pinia -S
  • 修改src/index.js
  • 创建src/pinia/index.js

src/index.js代码

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { createPinia } from "pinia";

const piniaStore = createPinia();

let app = createApp(App);
app.use(router).use(piniaStore);

app.mount("#app");

src/pinia/index.js代码

import { defineStore } from "pinia";

export const useTestStore = defineStore("counter", {
  state: () => {
    return { count: 0 };
  },
  getters: {},
  actions: {
    setCount(val) {
      this.count = val;
    },
  },
});

src/App.vue代码

<template>
  <div class="app">
    <router-link to="/">home</router-link>
    <router-link to="/about">home</router-link>
    <div>pinia -- {{ counter.count }}</div>
    <button @click="changePiniaCount">点击修改Pinia count的值</button>
    <router-view></router-view>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from "vue";

import { useTestStore } from "./pinia";


const counter = useTestStore();

let changePiniaCount = () => {
  // counter.count++;
  // counter.$patch({
  //   count: counter.count + 1,
  // });
  // counter.$patch((state) => {
  //   state.count++;
  // });
  counter.setCount(counter.count + 1);
};
</script>

<style></style>

5.安装axios

  • npm i axios -s
  • 封装一个基本的axios

首先先在src文件夹下面建立util文件夹,然后添加两个文件,分别是axios.js和request.js src/axios.js代码

import axios from "axios";
let baseURL = "https://api.github.com/";

const instance = axios.create({
  baseURL,
  timeout: 3000,
});

instance.interceptors.request.use(
  (config) => {
    return config;
  },
  (err) => {
    err.data = {};
    err.data.msg = "请求出错,请重新再试试";
    return Promise.reject(err);
  }
);

instance.interceptors.response.use(
  (response) => {
    if (response.status === 200) return response.data;
    else return "请求有误";
  },
  (err) => {
    err.data = {};
    err.data.msg = "请求出错,请重新再试试";
    return Promise.reject(err);
  }
);

export default instance;

src/request.js代码:

import instance from "./axios";

let post = ["put", "patch", "post"];

export default function getData(url, method, data) {
  return new Promise((resolve, reject) => {
    let options = {
      url,
      method,
    };

    if (post.includes(url)) {
      options.data = data;
    } else {
      options.params = data;
    }

    instance
      .get(url, options)
      .then((res) => {
        resolve(res);
      })
      .catch((err) => {
        reject(err);
      });
  });
}

然后在src/index.js引入函数

import getData from "@/util/request.js";
app.config.globalProperties.getData = getData;

在src/views文件夹下面新建个getData.vue

<template>
  <div>数据 <img :src="data.avatar_url" alt="" /></div>
</template>

<script setup lang="ts">
import { getCurrentInstance, onMounted, reactive } from "vue";
const instance = getCurrentInstance();

let data = reactive({
  avatar_url: "",
});

onMounted(async () => {
  let res = await instance.appContext.config.globalProperties.getData(
    "/users/ruanyf",
    "get",
    {}
  );
  Object.assign(data, res);
  console.log("data", data);
});
</script>

<style></style>

在src/router/index.js里面添加代码:

const routes = [
  ...,
  {
    path: "/data",
    name: "Data",
    component: () => import("@/views/getData.vue"),
  },
]

6.安装element-plus(三选一)

  • npm install element-plus --save
  • npm install -D unplugin-vue-components unplugin-auto-import

配置webpack

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()],
        }),
    ]
}

在src/views下面新建个element.vue文件

<template>
  <div style="margin-top: 10px">
    <el-button>Default</el-button>
  </div>
</template>

<script setup lang="ts"></script>

<style></style>

修改src/router/index.js代码

const routes = [
    ...,
    {
        path: "/element",
        name: "Element",
        component: () => import("@/views/element.vue"),
    },
]

7.安装antd-vue(三选一)

  • npm install ant-design-vue --save
  • npm install babel-plugin-import --save-dev

新增babel.config.js代码

module.exports = [
    plugins : [
        ...,
        [
          "import",
          { libraryName: "ant-design-vue", libraryDirectory: "es", style: "css" },
        ], // `style: true` 会加载 less 文件
    ]
]

然后新建src/views/antdVue.vue,代码

<template>
  <div>
    <Button>123</Button>
  </div>
</template>

<script setup lang="ts">
import { Button } from "ant-design-vue";
</script>

<style></style>

src/router/index.js代码

const routes = [
    ...,
    {
        path: "/antd",
        name: "Antd",
        component: () => import("@/views/antdVue.vue"),
    },
]

8.安装vant(三选一)

  • npm i vant -save
  • npm i unplugin-vue-components -D

按照官方文档的操作 按需引入有问题 在等等看看有没有人能解决 这里先局部引入 src/views/vants.vue代码

<template>
  <div>
    <van-button type="primary">主要按钮</van-button>
  </div>
</template>

<script>
import { Button } from "vant";

export default {
  components: {
    "van-button": Button,
  },
};
</script>

<style></style>

src/index.js代码

import "vant/lib/index.css";

src/router/index.js代码

const routes = [
  {
    path: "/vants",
    name: "Vants",
    component: () => import("@/views/vants.vue"),
  },
]

按需引入问题如下

image.png

9.规范

具体可以参考另外一篇文章 从 0 开始手把手带你搭建一套规范的 Vue3.x 项目工程环境

猜你喜欢

转载自juejin.im/post/7110270958258094088