当前位置:首页 > 技术 > Nuxt.js初上手(含axios封装、百度统计代码、Nginx配置文件等步骤)

Nuxt.js初上手(含axios封装、百度统计代码、Nginx配置文件等步骤)

伪管理员3年前 (2023-02-23)技术1270

    因新项目对SEO有需求,而自己也对Vue语法较为熟悉,早就在官网上看到过Nuxt.JS的简介不过一直也没有时间来折腾下。这次项目从本地运行到部署花了2天,其中有一部分坑也是摸索着才想出来,故此记录一下流程。

    本篇文章的Axios封装部分借鉴了博客 Nuxt中Axios的封装及接口统一管理方案 ,虽然可以再分开将不同类型的Api分散在各个文件后通过 require.context() 去实现自动导入,不过鉴于本项目规模有限就不再往这部分折腾,有兴趣的小伙伴也可以参照另一篇博客 (https://blog.csdn.net/weixin_41852038/article/details/122115948,不过据评论反馈无法直接运行,请甄别后使用) 来实现。

1.本地开发环境搭建

    可能由于Nuxt3出来,Nuxt2项目当我用NodeJS 的V18版本运行项目时提示失败,切换到Node v16.19.1版本后正常运行。考虑到这类多版本Node共存的需求,本地主机上装个Node版本管理工具还是很有必要的。这里我就直接用朋友推荐的 Volta来实现,Volta的使用还算简单,有时间可以另外开一篇来讲。总之,该项目Node版本固定后暂时调用官方的脚手架创建方法来进行。

# 使用create-nuxt-app 来创建项目,提示没有该命令的可以先试用npm i -g create-nuxt-app 安装项目启动包的启动包
npm init nuxt-app foo-bar
# 随后是选项的方式,按需选择,我的选择如下
programming language- js
package manager - npm
ui framework - vuetify # 或者Elementui也可
template engine - html
nuxt.js modules - axios
linting tools - prettier
testing framework - none
rendering mode server(nodejs hosting)
deployment tools jsconfig.json
CI none
version control system - git

等待包安装完,用IDE进入项目开始编辑

2.Axios封装

    由于项目创建时已集成Axios,故此处基本不再需要在Nuxt配置文件中额外配置Axios。基本步骤如下

    1. 项目根文件夹创立api文件夹,用于存放请求的接口 -- @/api/index.js

 
 export default ($axios) => {
   return {
     getData: () => $axios.get('/get_index_data'),
     // 有参数的情况
     postData: data => $axios.post('/get_index_data', data),
     getData: params => $axios.get('/get_index_data', {params}),
     // ...your other api function
     // 如按条件获取课程
     getCourseList: data => $axios.post('/service/courseFront/getCourseList', data),
   }
 }

    2. plugins文件夹创建request.js封装api请求


 // 引入创建的index.js api文件
 import req from '@/api/index.js'
 
 export default function ({ $axios, store }, inject) {
   function axiosConfig($axios) {
     let requestConfig = {}
     // 设置API的域名,注意生产环境已用nginx对/api进行proxy
     const baseUrl = process.env.NODE_ENV === 'development' ? 'http://localhost:3000/api' : `http://xxx.com/api`
     $axios.setBaseURL(baseUrl)
     // 设置请求拦截
     $axios.onRequest((config) => {
       // 用于调试
       if (process.env.DEBUG) {
         console.log('$axios.onRequest', config)
       }
       requestConfig = {
         baseURL: config.baseURL,
         url: config.url,
         method: config.method,
         data: config.data,
         headers: config.headers,
         params: config.params,
       }
 
       config.startTime = new Date().getTime()
       config.headers['Content-Type'] = 'application/json'
       /* 如果需要token */
       const token = store.state.token || ''
       if (token) {
         // config.headers.Authorization = `Bearer ${token}`
         config.headers.token = `${token}`
       }
       return config
     })
     // 设置响应拦截
     $axios.onResponse((response) => {
       response.config.endTime = new Date().getTime()
       const status = response.status
 
       if (+status === 200) {
         // 打印出每个接口的响应时间,如果慢了就捶后端,让他优化!!!
         console.info(response.config.url, '请求时间', response.config.endTime - response.config.startTime + 'ms'
         )
         // 用于调试
         if (process.env.DEBUG) {
           console.info('$axios.onResponse', response.data)
         }
         // 返回接口数据
         return response.data
       } else {
         // 如果请求失败的,打印出相应的错误信息,更好的修改。
         const responseConfig = response ? response.config : {}
         console.error('响应拦截报错提示: ', {
           url: responseConfig.baseURL + responseConfig.url,
           status: response.status,
           statusText: response.statusText,
           method: responseConfig.method,
           headers: responseConfig.headers,
           data: responseConfig.data,
           params: responseConfig.params,
           responseData: response.data,
         })
       }
     })
 
     // axios错误处理
     $axios.onError((error) => {
       const response = error.response || {}
       const responseConfig = response.config || {}
       console.error('$axios.onError: ', error)
       console.error('错误处理提示 ', {
         url: responseConfig.baseURL + responseConfig.url,
         status: response.status,
         statusText: response.statusText,
         method: responseConfig.method,
         headers: responseConfig.headers,
         data: responseConfig.data,
         params: responseConfig.params,
         responseData: response.data,
         ...requestConfig,
       })
     })
     // 最后返回$axios对象
     return $axios
   }
   inject('req', req(axiosConfig($axios.create())))
 }


    3. nuxt.config.js引入request.js文件

        

 export default {
  ... // other code
   plugins: [
     '~/plugins/request',
   ],
   // 配合上述/api实现本地开发时使用代理
   // Modules: https://go.nuxtjs.dev/config-modules
   modules: [
     // https://go.nuxtjs.dev/axios
     '@nuxtjs/axios',
     '@nuxtjs/proxy',
   ],
 
   // Axios module configuration: https://go.nuxtjs.dev/config-axios
   axios: {
     // Workaround to avoid enforcing hard-coded localhost:3000: https://github.com/nuxt-community/axios-module/issues/308
     // baseURL: '/api', // 此处不备注掉会出现请求前实际出现2个/api,因已调用axios的封装此处不再设置baseURL
     proxy: true,
   },
   proxy: {
     '/api': {
       target: 'http://xx.cn/api',
       pathRewrite: { '^/api': '', },
       changeOrigin: true,
     }
   },
     ... // other code
 }


    4. 使用

    asyncData

    

 async asyncData({ $indexApi }) {
     const res = await $indexApi.getData()
     
     let data = []
     
     if(res.status) {
         data = res.data
     }
     
     return {
         data
     }
 },

    store

 export const actions = {
   async getData({ commit }) {
     const res = await this.$indexApi.getData()
 
     if (res.state) {
       commit('SET_INDEX_DATA', res.data)
     } else {
       throw new Error(res)
     }
   }
  }

    method

 export default {
  methods: {
         async getData() {
             await this.$indexApi.getData()
             // code something
         }
     }  
 }

    以上步骤启动后,再在项目中运行基本可以了。悲催的是我在配置Axios的BaseUrl那里沿用了Vue/CLI项目的习惯,开发环境下设的BaseURL是 '/api',结果asyncData中调用这个方法就是不成功(报错 connect ECONNREFUSED ::1:80),而在mounted周期内是客户端调用该方法就没问题,网上直接搜这个问题没答案,但有位仁兄的想法是这个请求地址是直接使用 /api/*** 进行访问的,默认是向本机80端口发送请求,而我本地80端口没跑服务自然报错,后来反复测试把生产环境下的BaseURL设为了项目启动的地址 http://localhost:3000/ 再去请求果然就可以了 ;生产环境中由于提前用Nginx进行了代理,因此生产环境中是正常的。


3.百度统计


    点击跳转 百度统计, 这个用来统计网站访问情况等等的还是很好用的

    1. 项目根目录的plugin文件夹内添加baidu.js

 export default ({app: {router}, store}) => {
   /* 每次路由变更时进行pv统计 */
   router.afterEach((to, from) => {
     /* 告诉增加一个PV */
     try {
       window._hmt = window._hmt || []
       window._hmt.push(['_trackPageview', to.fullPath])
     } catch (e) {
     }
   })
 }

    2. nuxt.config.js中添加以下配置

export default {
   head:{
     script: [
       // xxxx是百度统计分配的代码
       { src: 'https://hm.baidu.com/hm.js?xxxxxxxxx' },
     ],
   },
   plugins:['@/plugins/baidu']
 }

4.服务器部署

    1. 服务器安装node

    此处使用CentOS7.9 进行安装,进入想要安装的目录(此处为 /usr/local/node-v16.19.1)依次运行下列程序

    wget https://nodejs.org/dist/v16.19.1/node-v16.19.1-linux-x64.tar.xz
     
   # 解压
   xz -d node-v16.19.1-linux-x64.tar.xz
   tar -xvf node-v16.19.1-linux-x64.tar
   # 进入目录
   cd node-v16.19.1-linux-x64/
     
   # 创建软连接
   ln -sf /usr/local/node-v16.19.1-linux-x64/bin/node /usr/local/bin/node
   ln -sf /usr/local/node-v16.19.1-linux-x64/bin/npm /usr/local/bin/npm
     
   # 测试
   node -v
   npm -v

    2.安装pm2并软连接

    命令find / -name pm2找到pm2安装目录(使用bin文件夹下的),按上述node安装位置是在/usr/local/node-v16.19.1-linux-x64/bin/pm2,建立软连接ln -s /usr/local/node-v16.19.1-linux-x64/bin/pm2 /usr/local/bin为避免日志问题可安装pm2插件进行日志分割pm2 install pm2-logrotate


        

    3. 项目打包

    项目打包 npm run build,随后将.nuxt目录static目录、nuxt.config.jspackage.json复制进项目在服务器上的文件夹/usr/share/nginx/html/nuxt.xx.cn/执行npm i安装依赖


    4. 项目运行

    修改该站点nginx配置文件(主要是配置反代)/etc/nginx/conf.d/nuxt.xx.cn.conf文件,同项目中的该文件,项目使用pm2启动,过程为进入项目根目录/usr/share/nginx/html/nuxt.xxx.cn/,按照官网在此处添加pm2启动文件ecosystem.config.js,随后在此处运行pm2 start即可启动项目,项目日志可通过网站app.pm2.io在线获取

ecosystem.config.js

 // ecosystem.config.js
 module.exports = {
   apps: [
     {
       name: 'vue_nuxt',
       exec_mode: 'cluster',
       instances: 'max', // Or a number of instances
       script: './node_modules/nuxt/bin/nuxt.js',
       args: 'start'
     }
   ]
 }

 Nginx配置文件
 

upstream nodenuxt {
   server 127.0.0.1:3000; #nuxt项目 监听端口
   keepalive 64;
 }
 
 server
 {
     listen       80;
     listen       [::]:80;
     server_name  nuxt.xxx.cn;
     index index.php index.html index.htm default.php default.htm default.html;
     root /usr/share/nginx/html/nuxt.xxx.cn/.nuxt/dist;
 
     gzip on;
     gzip_min_length 1k;
     gzip_comp_level 5;
     gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
     gzip_disable "MSIE [1-6]\.";
     gzip_vary on;
 
 
     location / {
         # root /usr/share/nginx/html/nuxt.xx.cn/.nuxt/dist/;
         # try_files $uri $uri/ /index.html; #https://v3.router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90
         # index  index.html index.htm;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "upgrade";
         proxy_set_header Host $host;
         proxy_set_header X-Nginx-Proxy true;
         proxy_cache_bypass $http_upgrade;
         proxy_pass http://nodenuxt;
     }
 
     # 代理解决跨域
     location /api/ {
         proxy_pass http://xx.cn:8100/;
         proxy_redirect default;
     }
 
 
     # Load configuration files for the default server block.
     include /etc/nginx/default.d/*.conf;
 
     error_page 404 /404.html;
     location = /404.html {
     }
 
     error_page 500 502 503 504 /50x.html;
     location = /50x.html {
     }
 }


    以上,一个基础的Nuxt框架就搭好了,其他Nuxt开发注意事项可以访问Nuxt官方文档。若有什么问题欢迎各位留言,我看到将会尽力解答。

——一个初级前端


标签: VueNuxt.JSAxios
分享给朋友:
返回列表

上一篇:新起点

没有最新的文章了...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。