vite项目搭建

279 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

世间事,除了生死,哪一件不是闲事。

记 vite 项目创建的步骤

1. npm init @vitejs/app my-vue-app -- template vue-ts      // 创建名为my-vue-app的vite项目,使用vue和ts
2. cd my-vue-app    // 进入初始化完成的项目
3. npm install    // 安装项目依赖
4. npm run dev   // 运行项目
5. npm install less less-loader -s   // 安装less
6. npm install vue-router@4.0 -s    // 安装vue-router,这里选择了4.0以上的较高版本
7. npm install vuex@4.0 -s    // 安装vuex,这里选择4.0以上较高版本

vue-router

安装完成vue-router之后,在项目src目录下面新建router目录,然后添加index.ts文件,在文件中添加以下内容。

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

// 在Vue-router新版本中,需要使用createRouter来创建路由
export default createRouter({
  // 指定路由的模式,此处使用的是hash模式
  history: createWebHashHistory(),
  // 路由地址
  routes: [],
});

vuex

安装完成vuex之后,在项目src目录下面新建store目录,并添加index.ts文件,文件中添加以下内容。

import { createStore } from "vuex";

interface State {
  userName: String;
}

export default createStore({
  state: {
    userName: "yuan",
  },
});

main.ts

在 main.ts 中引入 vuex 和 vue-router。

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

页面自适应

页面自适应配置按如下步骤操作即可,详情可参照:http://10.10.38.40/b2binfo3/pages/normalQuestion/Code_Adaptation.html#%E7%A7%BB%E5%8A%A8%E7%AB%AF

1.下载 pxtorem 插件

npm install postcss-pxtorem

2.vite.config.ts

配置 pxtorem 插件

export default defineConfig({
  plugins: [vue()],
  css: {
    postcss: {
      plugins: [
        require("postcss-pxtorem")({
          rootValue: 75, //75px=1rem,这个值可以自行修改
          propWhiteList: [],
          minPixelValue: 2,
        }),
      ],
    },
  },
});

3.解决 require 报错问题

在该文件中使用require报错找不到require。只需要按照报错提示安装以下包即可。

npm i --save-dev @types/node

4.创建并使用适配 js 文件

  1. public 目录下面,创建一个 dprFlex.js,js 内容如下:
(function(win, lib) {
  var doc = win.document;
  var docEl = doc.documentElement;
  var metaEl = doc.querySelector('meta[name="viewport"]');
  var flexibleEl = doc.querySelector('meta[name="flexible"]');
  var dpr = 0;
  var scale = 0;
  var tid;
  var flexible = lib.flexible || (lib.flexible = {});

  if (metaEl) {
    var match = metaEl
      .getAttribute("content")
      .match(/initial-scale=([\d.]+)/);
    if (match) {
      scale = parseFloat(match[1]);
      dpr = parseInt(1 / scale);
    }
  } else if (flexibleEl) {
    var content = flexibleEl.getAttribute("content");
    if (content) {
      var initialDpr = content.match(/initial-dpr=([\d.]+)/);
      var maximumDpr = content.match(/maximum-dpr=([\d.]+)/);
      if (initialDpr) {
        dpr = parseFloat(initialDpr[1]);
        scale = parseFloat((1 / dpr).toFixed(2));
      }
      if (maximumDpr) {
        dpr = parseFloat(maximumDpr[1]);
        scale = parseFloat((1 / dpr).toFixed(2));
      }
    }
  }

  if (!dpr && !scale) {
    var isAndroid = win.navigator.appVersion.match(/android/gi);
    var isIPhone = win.navigator.appVersion.match(/iphone/gi);
    var devicePixelRatio = win.devicePixelRatio;
    //可配置安卓和ios不同的适配
    if (isIPhone) {
      dpr = 1;
    } else {
      dpr = 1;
    }
    scale = 1 / dpr;
  }

  docEl.setAttribute("data-dpr", dpr);
  if (!metaEl) {
    metaEl = doc.createElement("meta");
    metaEl.setAttribute("name", "viewport");
    metaEl.setAttribute(
      "content",
      "initial-scale=" +
        scale +
        ", maximum-scale=" +
        scale +
        ", minimum-scale=" +
        scale +
        ", user-scalable=no"
    );
    if (docEl.firstElementChild) {
      docEl.firstElementChild.appendChild(metaEl);
    } else {
      var wrap = doc.createElement("div");
      wrap.appendChild(metaEl);
      doc.write(wrap.innerHTML);
    }
  }

  function refreshRem() {
    var width = docEl.getBoundingClientRect().width;
    var rem = width / 10;
    docEl.style.fontSize = rem + "px";
    flexible.rem = win.rem = rem;
  }

  win.addEventListener(
    "resize",
    function() {
      clearTimeout(tid);
      tid = setTimeout(refreshRem, 300);
    },
    false
  );
  win.addEventListener(
    "pageshow",
    function(e) {
      if (e.persisted) {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
      }
    },
    false
  );

  if (doc.readyState === "complete") {
    doc.body.style.fontSize = 12 * dpr + "px";
  } else {
    doc.addEventListener(
      "DOMContentLoaded",
      function() {
        doc.body.style.fontSize = 12 * dpr + "px";
      },
      false
    );
  }

  refreshRem();

  flexible.dpr = win.dpr = dpr;
  flexible.refreshRem = refreshRem;
  flexible.rem2px = function(d) {
    var val = parseFloat(d) * this.rem;
    if (typeof d === "string" && d.match(/rem$/)) {
      val += "px";
    }
    return val;
  };
  flexible.px2rem = function(d) {
    var val = parseFloat(d) / this.rem;
    if (typeof d === "string" && d.match(/px$/)) {
      val += "rem";
    }
    return val;
  };
})(window, window["lib"] || (window["lib"] = {}));
  1. 在 index.html 中将该 js 文件引入(<script src="/dprFlex.js"></script>)
  2. 做到这里项目重新运行即可在控制台看到,px单位都变成了rem单位。

配置全局样式

less

全局 less 变量文件需要在 vite.config.ts 中进行配置,这样在 less 文件中定义的变量就可以全局使用。

const { resolve } = require("path");

export default defineConfig({
  plugins: [vue()],
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          hack: `true; @import (reference) "${resolve(
            "./src/style/variable.less"
          )}";`,
        },
        javascriptEnabled: true,
      },
    },
  },
});

scss

全局 scss 变量文件需要在 vite.config.ts 中进行配置,这样在 scss 文件中定义的变量就可以全局使用。

export default defineConfig({
  plugins: [vue()],
  css: {
    cssPreprocessOptions: {
      scss: {
        additionalData: '@import "./src/assets/scss/style.scss";', // 添加公共样式
      },
    },
  },
});

vite.config.js 配置

vite 官网

base

base是用于配置打包后文件的路径,合法取值如下:

  • 绝对 URL 路径名,例如/foo/
  • 完整的 URL,例如http://yuanchengcheng.com/
  • 空字符串或./(常用,记着项目一定要配,不然部署后获取不到文件)

build.outDir

outDir用于指定打包文件的输出路径,相对于根目录,默认为dist