【搭建一个vue项目只需要简单几步】


前言

按着自己习惯的环境版本号来.一共分为一下文件夹


一、public

index.html代码如下

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> 
    <meta name="apple-mobile-web-app-capable" content="yes"> 

    <link rel="icon" href="https://图片地址" type="image/x-icon" />
    <title>DivergenceValueSimulator</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

二、src

1.api

api.js

import http from './http'
// 密码登录 
export const login = params => { return http.post('/login', params).then(res => res.data); };

http.js

import axios from 'axios';
import qs from 'qs';
import Vue from 'vue';
Vue.prototype.$axios = axios;
import { Toast } from "vant";
axios.defaults.baseURL = 'http://192.168.61.16:8009'
axios.defaults.timeout = 1000 * 30
axios.defaults.withCredentials = false; // true: 不允许跨域
function request(url, data = {}, method) {
  return new Promise(function (resolve, reject) {
    var headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': localStorage.getItem("token") || localStorage.getItem("guest_token") || "",
    }
    var conf = {
      method: method,
      url: url,
      headers: headers,
      data: data
    }
    method === 'POST' ? conf.data = data : conf.params = data
    axios(conf).then((res) => {
      if (res.status == 200) {
        if (res.data.Code == '0') {
          resolve(res)
        } else {
          if (res.data) {
            // reject(res.data)
            resolve(res)
          }
        }
      }
    }).catch((res) => {
      reject(res.response)
      if (res.response) {
        if (res.response.status === 500) {
          Toast("网络打了个盹,请刷新页面");
        } else {
          Toast(res.response.data.Message || "请重试");
          if (res.response.status == 403) {
            // Toast("请先登录");
            localStorage.removeItem("token");
            localStorage.removeItem("guest_token");
            sessionStorage.removeItem("loginStatusBli");
            sessionStorage.removeItem("loginStatusGame");
            // setTimeout(function () {
              // window.location.href = "http://192.168.61.21:8088/#/";
            // }, 1000)
          }
        }
      }
    })
  })
}
export default {
  get(url, data = {}) {
    return request(url, data, 'GET')
  },
  post(url, data = {}) {
    return request(url, data, 'POST')
  },
}

2.assets

放资源,图片,视频,字体

3.common

utils.js 自定义的一些方法,这里展示判断移动端的方法

export const isIpadFun = function() {
  var ua = window.navigator.userAgent
  var IsIPad = false
  if (/ipad/i.test(ua)) {
    IsIPad = true
  }
  // iPad from IOS13
  var macApp = ua.match(/Macintosh/i) != null
  if (macApp) {
    // need to distinguish between Macbook and iPad
    var canvas = document.createElement('canvas')
    if (canvas != null) {
      var context =
        canvas.getContext('webgl') || canvas.getContext('experimental-webgl')
      if (context) {
        var info = context.getExtension('WEBGL_debug_renderer_info')
        if (info) {
          var renderer = context.getParameter(info.UNMASKED_RENDERER_WEBGL)
          if (renderer.indexOf('Apple') != -1) IsIPad = true
        }
      }
    }
  }
  return IsIPad;
}
export const  isMobileDevice = function() {
  return navigator.userAgent.match(
    /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i
  );
}

export default {
  isIpadFun,
  isMobileDevice, 
}

vant.js 引入的前端UI框架,按需引入

import Vue from 'vue'

import { Popup, Form, Field, Toast, Loading, Button } from 'vant';
Vue.use(Popup);
Vue.use(Form);
Vue.use(Field);
Vue.use(Loading);
Vue.use(Toast);
Vue.use(Button);

4.components

自定义的公共组件文件夹

5.router

index.js

import Vue from 'vue'
import Router from 'vue-router'

import index from "../views/index.vue";
import home from "../views/home/home.vue";

Vue.use(Router)
export default new Router({
  mode: 'history',
  base: process.env.NODE_ENV==='production' ? '/OperationEndless2063' : '/',
  routes: [
    {
      path: '/',
      name: 'index',
      component: index,
    },
    {
      path: '/home',
      name: 'home',
      component: home,
      children: [
        // {
        //   path: '/game',
        //   name: 'game',
        //   component: game,
        // },
        // {
        //   path: '/access',
        //   name: 'access',
        //   component: access,
        // },
        // {
        //   path: '/atlas',
        //   name: 'atlas',
        //   component: atlas,
        // },
      ]
    },
  ]
})

6.store

index.js vuex状态管理器

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    targetScroll: sessionStorage.getItem('targetScroll') || 0,
  },
  mutations: {
    setTargetScroll(state, arr) {
      sessionStorage.setItem('targetScroll', arr)
      state.targetScroll = arr
    },
  }
})
export default store;

7. style

main.css 公共样式文件,在main.js中引入

body, html {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

8.views

放页面的文件夹

9.App.vue

<template>
  <div id="app">
    <router-view />
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
    }
  },
  created() {
  },
  mounted() {},
  methods: {},
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  width: 100%;
  height: 100%;
  overflow-y: hidden;
  overflow-x: hidden;
}
</style>

10.main.js

import vuescroll from 'vuescroll';
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import moment from 'moment';
import lodash from "lodash";

import "./style/main.css";
import "./common/vant";

moment.locale('zh-cn')
Vue.prototype.$moment = moment;

Vue.use(vuescroll, {
  ops: {
    vuescroll: {
      mode: "native",
      detectResize: true,  //内容是否根据页面调整
    },
    bar: {
      showDelay: 500,
      onlyShowBarOnScroll: false, //是否只有滚动的时候才显示滚动条
      keepShow: true,
      background: '#eeeeee',
      opacity: 0,
      hoverStyle: false,
      specifyBorderRadius: false,
      minSize: false,
      size: '6px',
      disable: false,
      overflowX: 'hidden',
    },
    scrollPanel: {
      speed: 800,       //多长时间内完成一次滚动。 数值越小滚动的速度越快。
      easing: 'easeInQuad', //默认动画
    }
  },
  name: 'vueScroll' // 在这里自定义组件名字,默认是vueScroll
});

// import proNav from "./components/proNav.vue";
// Vue.component("proNav", proNav)
Vue.component('vueScroll', vuescroll);
Vue.config.productionTip = false


new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

三 babel.config.js

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      // style: true
      style: (name) => `${name}/style/less`,
    }, 'vant']
  ]
}

四 package-lock.json

可以为空,会自定下载

五 package.json

{
  "name": "part3",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack serve --open"
  },
  "keywords": [],
  "author": "juaner",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.18.2",
    "@vue/cli-plugin-babel": "^5.0.8",
    "babel-loader": "^8.2.5",
    "babel-plugin-import": "^1.13.5",
    "clean-webpack-plugin": "^4.0.0",
    "core-js": "^3.22.8",
    "css-loader": "^6.7.1",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.5.0",
    "html-withimg-loader": "^0.1.16",
    "image-webpack-loader": "^8.1.0",
    "less": "^4.1.3",
    "less-loader": "^11.0.0",
    "optimize-css-assets-webpack-plugin": "^6.0.1",
    "postcss": "^8.4.14",
    "postcss-loader": "^7.0.0",
    "postcss-preset-env": "^7.7.1",
    "style-loader": "^3.3.1",
    "terser-webpack-plugin": "^5.3.9",
    "ts-loader": "^9.3.1",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^4.1.1",
    "vant": "^2.13.0",
    "vue-loader": "^15.9.8",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.73.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.9.2",
    "wowjs": "^1.1.3"
  },
  "dependencies": {
    "@studio-freight/lenis": "^1.0.27",
    "animate.css": "^4.1.1",
    "ar-style": "^0.1.3",
    "axios": "^0.27.2",
    "gsap": "^3.12.2",
    "html2canvas": "^1.0.0-rc.4",
    "js-md5": "^0.7.3",
    "live2d-widget": "^3.1.4",
    "moment": "^2.29.4",
    "streamsaver": "^2.0.6",
    "swiper": "^3.4.2",
    "vue": "^2.6.14",
    "vue-clipboard2": "^0.3.1",
    "vue-kinesis": "^1.3.3",
    "vue-mobile-audio": "^0.1.3",
    "vue-router": "^3.5.4",
    "vue-template-loader": "^1.1.0",
    "vue-touch": "^2.0.0-beta.4",
    "vuescroll": "^4.17.0",
    "vuex": "^3.1.1"
  }
}

六 webpack.config.js

// webpack的配置文件
// 引入一个包
const path = require('path');
// 引入html插件
const HTMLWebpackPlugin = require('html-webpack-plugin');
// 引入clean插件(不是默认的,需要写在{}里面),作用就是清除dist文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
// babel 把新语法转换成旧语法,让代码兼容性更好\
const TerserPlugin = require('terser-webpack-plugin'); // 压缩js


// webpack中的所有配置信息都应该写到module.exports中
module.exports = {
  // publicPath: process.env.NODE_ENV==='production' ? '/aaa/' : './',
  // 开发环境 development(production:生产环境)
  mode: "development",
  // 指定入口文件
  entry: "./src/main.js",
  devtool: false,
  // devtool: 'eval-cheap-module-source-map', // 开发环境
  // 指定打包文件所在的目录
  output: {
    // 指定打包文件的目录
    path: path.resolve(__dirname, "dist"),
    // 打包后的文件
    filename: "bundle.[contenthash:10].js",
    // 每次打包后是否清除dist
    clean: true,
    // 配置打包环境
    environment: {
      // 告诉webpack不适用箭头函数
      arrowFunction: false
    }
  },
  devServer: {
    open: true,
    host: "192.168.61.21",
    port: "8084"
  },
  // 指定webpack打包时要使用的模块
  module: {
    // 指定要加载的规则
    rules: [
      // 配置vue
      {
        test: /\.vue$/,
        use: ['vue-loader'],
      },
      {
        test: /\.js$/,
        include: path.resolve("src"),
        use: ['babel-loader'],
      },
      // 设置less文件的处理
      {
        test: /\.less|.css$/,
        use: [
          "style-loader",
          "css-loader",
          // 引入postcss(让css兼容性更好)
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  [
                    "postcss-preset-env",
                    {
                      browsers: "last 2 versions"
                    }
                  ]
                ]
              }
            }
          },
          "less-loader"
        ]
      },
      // 背景图片处理规则
      {
        test: /\.(jpg|png|gif|bmp|jpeg)$/,
        use: {
          loader: "url-loader",
          options: {
            // publicPath: '/',
            name: 'image/[name].[ext]',
            esModule: false,
            limit: 0 * 1024, // 将小于4kb的图片用based64处理
            // publicPath: '/',
          }
        },
        type: 'javascript/auto' //转换 json 为 js
      },
      // 视频音频
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'file-loader',
        options: {
          name:'audios/[name].[ext]',
          // publicPath: '/',
          esModule: false,
        }
      },
      // html图片
      {
        test: /\.(htm|html)$/,
        loader: 'html-withimg-loader'
      },
      // 通过资源模块来处理字体
      // {
      //   test: /\.(eot|svg|ttf|otf|woff|woff2)$/i,
      //   type: 'asset/resource',
      //   generator: {
      //     filename: "fonts/[name]_[hash:9][ext]" // 单独指定 名字
      //   }
      // },
      // 压缩图片(要搭配url-loader一起使用)
      {
        loader: 'image-webpack-loader',
        options: {
          mozjpeg: {
            progressive: true,
            quality: 60
          },
          optipng: {
            enabled: false,
          },
          pngquant: {
            quality: [0.65, 0.90],
            speed: 4
          },
          gifsicle: {
            interlaced: false,
          },
          //ios不支持
          // webp: {
          //  quality: 100
          // }
        }
      }
    ]
  },
  optimization: {
    usedExports: true, // 配合实现 Tree Shaking,,默认 true 开启
    concatenateModules: true, // 公共代码整合,生产环境下被启用
    minimize: true, // 在生成环境是否开启js代码压缩和Tree Shaking,默认 true 开启
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true, // 去除console
          },
        },
        extractComments: false, // 默认:true,当 minimize为true 打包时会生成注释文件,参数为 false 不生成注释文件
      }),
    ],
  },
  // 配置webpack插件
  plugins: [
    new HTMLWebpackPlugin({
      // favicon: path.resolve(__dirname, './public/favicon.ico'),
      template: path.resolve(__dirname, "./public/index.html")
    }),
    new CleanWebpackPlugin(),
    new VueLoaderPlugin(),
  ],
  // 用来设置引用模块的,哪些文件可以用来做为引用模块
  resolve: {
    // 以ts,js结尾的文件可以用来引用
    extensions: ['.ts', '.js']
  },
}
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值