vue项目目录构建与配置

3,402 阅读3分钟

前言

使用vue构建项目,项目结构清晰会提高开发效率,熟悉项目的各种配置同样会让开发效率更高,本篇幅不长,纯属分享,希望帮助小白提高开发效率,也欢迎大神讨论指正

目录结构

my-vue-test:.
│  .browserslistrc
│  .env.production
│  .eslintrc.js
│  .gitignore
│  babel.config.js
│  package-lock.json
│  package.json
│  README.md
│  vue.config.js
│  yarn-error.log
│  yarn.lock
│
├─public
│      favicon.ico
│      index.html
│
└─src
    ├─apis //接口文件根据页面或实例模块化
    │      index.js
    │      login.js
    │
    ├─components //工具组件
    │  └─header
    │          index.less
    │          index.vue
    │
    ├─config //配置(环境变量配置不同passid等)
    │      env.js
    │      index.js
    │
    ├─contant //常量
    │      index.js
    │
    ├─images //图片
    │      logo.png
    │
    ├─pages //多页面vue项目,不同的实例
    │  ├─index //主实例
    │  │  │  index.js
    │  │  │  index.vue
    │  │  │  main.js
    │  │  │  router.js
    │  │  │  store.js
    │  │  │
    │  │  ├─components //业务组件
    │  │  └─pages //此实例中的各个路由
    │  │      ├─amenu
    │  │      │      index.vue
    │  │      │
    │  │      └─bmenu
    │  │              index.vue
    │  │
    │  └─login //另一个实例
    │          index.js
    │          index.vue
    │          main.js
    │
    ├─scripts //包含各种常用配置,工具函数
    │  │  map.js
    │  │
    │  └─utils
    │          helper.js
    │
    ├─store //vuex仓库
    │  │  index.js
    │  │
    │  ├─index
    │  │      actions.js
    │  │      getters.js
    │  │      index.js
    │  │      mutation-types.js
    │  │      mutations.js
    │  │      state.js
    │  │
    │  └─user
    │          actions.js
    │          getters.js
    │          index.js
    │          mutation-types.js
    │          mutations.js
    │          state.js
    │
    └─styles //样式统一配置
        │  components.less
        │
        ├─animation
        │      index.less
        │      slide.less
        │
        ├─base
        │      index.less
        │      style.less
        │      var.less
        │      widget.less
        │
        └─common
                index.less
                reset.less
                style.less
                transition.less

vue.confing.js配置

vue.config.js通常是一份写好后可以不断复制,但是会用不如会写,需要知道里面的原理,多页面使用nodejs来配置多个入口,代码更加优雅,下面是一份常用的vue.config.js配置,附注释

const path = require("path")
const fs = require("fs")

/**
 * @readdirSync fs模块,用于读取文件夹下所有的文件/文件夹,返回数组,fs.readdir的同步版本
 * @resolve path模块,用于拼接文件路径
 * @existsSync fs模块,判断路径是否存在,返回布尔值
 */
const dirs = fs.readdirSync(path.resolve(process.cwd(), "src/pages"))
const pages = dirs.reduce((config,dirname)=>{
    const filePath = `src/pages/${dirname}/main.js`
    const tplPath = path.resolve(process.cwd(), `./public/${dirname}.html`)

    if(fs.existsSync(tplPath)){
        config[dirname] = filePath
    }else{
        config[dirname] = {
            entry:filePath,//page的入口
            template:'public/index.html',//模板的来源
            filename:`${dirname}.html`//在dist/xx.html输出
        }
    }
    return config
},{})
// 多页面 pages 使用的模版默认为 public/[dir-name].html,如果找不到该模版,默认使用 public/index.html

/**
 * publicPath: 应用会默认部署在根路径,使用publicPath可以定义部署在子路径,pages模式不要使用相对路径
 * productionSourceMap: 为true 则打包会生成.map文件
 * contentBase: 告诉服务器从那个目录提取静态文件
 * compress: 一切服务都启用 gzip 压缩
 * historyApiFallback: 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html
 * disableHostCheck: 绕过主机检查
 * devServer.proxy.changeOrigin: 默认情况下,代理时会保留主机标头的来源,您可以将changeOrigin设置为true来覆盖此行为
 * devServer.proxy.secure: 默认情况下,不接受运行在 HTTPS 上,且使用了无效证书的后端服务器,设置为false表示接受
 * chainWebpack: webpack的链式操作
 * configureWebpack:可能是个对象,也可能是个函数,主要是通过webpack-merge合并到配置里
 * configureWebpack.resolve: 相当于合并内容到webpack原来的resolve[https://webpack.docschina.org/configuration/resolve/#resolve]
 * configureWebpack.resolve.alias: 创建 import 或 require 的别名,来确保模块引入变得更简单
 */
module.exports = {
    publicPath: process.env.VUE_APP_MODE === "production" ? "/prod/" : "/",
    pages,
    outputDir:process.env.VUE_APP_MODE === "production"? path.resolve(`${process.cwd()}/dist-prod/`):path.resolve(`${process.cwd()}/dist-beta/`),
    productionSourceMap:process.env.VUE_APP_MODE === "beta",
    devServer:{
        port:3434,
        host: "127.0.0.1",
        contentBase: "./dist",
        compress:true,
        historyApiFallback:true,
        disableHostCheck: true,
        proxy:{
            "/": {
                target: "http://10.122.122.10:8070",
                changeOrigin: true,
                secure: false,
                // pathRewrite: {"^/sjjc" : ""}
              },
        }

    },
    chainWebpack: config => {
        config.module
          .rule("images")
          .use("url-loader")
          .tap(args => {
            return {
              limit: 4096,
              fallback: {
                loader: "file-loader",
                options: {
                  name: "images/[name].[hash:8].[ext]",
                },
              },
            };
          });
        config.module
          .rule("svg")
          .use("file-loader")
          .tap(args => {
            return {
              name: "images/[name].[hash:8].[ext]",
            };
          });
      },
      configureWebpack: {
        resolve:{
            alias:{
                "@_src": path.resolve(__dirname,"src/")
            }
        }
      }
}

.env环境变量配置

  • 在根目录下配置.env文件,可以设置环境变量(可设置多个)

    • .env.produciton.env.development
  • 全局变量仅除NODE_ENVBASE_URL这两个保留变量外,其余自定义变量都需使用VUE_APP开头。

    • VUE_APP_MODE=beta
  • 注意点.env文件里不允许存在注释

/**
* .env.produciton内部写法
*/

NODE_ENV=production
VUE_APP_MODE=production

store模块化使用

使用store模块化配合路由守卫,可以实现不同路由在页面上的不同配置,例如特定路由需要展示不同的样式,特定路由不需要头部,不需要侧边导航栏等,这些可以在router.js中配置路由守卫,利用store定义各个属性,实例化前通过mapstate拿到配置,实现不同路由不同样式的效果

store的模块化

->@_src/store/index.js

// @_src/store/index.js

import Vuex from "vuex";
import Vue from "vue";

import index from "./index/index.js";
import user from "./user";
Vue.use(Vuex);
const stores = {
  "index": index,
  user,
};

export const storeCreator = (moduleNames) => {
  const names = Array.isArray(moduleNames) ? moduleNames : [moduleNames];
  const modules = names.reduce((all, name) => {
    if (stores[name]) {
      all[name] = stores[name];
    }
    return all;
  }, {});

  return new Vuex.Store({
    modules: {
      ...modules
    }
  });
};

各个实例中的store引入

->@_src/pages/index/store.js

import { storeCreator} from "@_src/store"

export default storeCreator(["index","user"])

store模块化配合路由守卫实现不同路由的样式配置

  • router.js
import Vue from "vue"
import VueRouter from "vue-router"
import store from "./store";

export const routes = [
    //初始进入重定向至父级通用事项页面
  {
    path: "/",
    redirect: "/a-menu",
    name: "home"
  },
  {
    name: "菜单A",
    path: "/a-menu",
    component: () => import("./pages/amenu/index.vue"),
    meta: { title: "菜单A",icon:"xxx", menuCode: "xxx"}
  },
  {
    name: "菜单B",
    path: "/b-menu",
    component: () => import("./pages/bmenu/index.vue"),
    meta: { title: "菜单A",icon:"xxx", menuCode: "xxx"}
  },
]

// header的title的颜色是否为白色路由
const writeTitleRoutes = [
  {
    path: "/b-menu",
    name: "菜单B",
  },
];

Vue.use(VueRouter);
const router = new VueRouter({
  routes
});

//配置路由导航守卫

router.beforeEach((to,from,next)=>{
  let writeTitle=false
  for(let i=0;i<writeTitleRoutes.length;i++){
    const pathReg = new RegExp(writeTitleRoutes[i].path);
    if (pathReg.test(to.path)) {
      writeTitle = true;
      break;
    }
  }

  if (store.state.index.writeTitle !== writeTitle) {
    store.commit("index/SET_TITLE", writeTitle);
  }
  next();
})

export default router;