當前位置:網站首頁>nuxt項目總結-綜合

nuxt項目總結-綜合

2022-01-28 04:29:08 MatchstickMen_roukun

技術棧選擇

由於項目需要考慮SEO,而我又不想寫原生HTML+CSS+JS,想使用Vue去寫
所以打算使用只學過沒用過的Nuxt(SSR)框架去寫,同時在Javascript與Typescript語言的選擇,
選擇Typescript的原因是:沒用過,想Try Try;如果選擇了Typescript,那就不能直接用Vue的OptionAPI,選擇vue-property-decorator的ClassAPI更加友好,而兼容nuxt的classAPI的依賴有nuxt-property-decorator

存儲方式選擇localforage代替localstorage
原因:1.localstorage存儲比較慢,但localforage能够輕松實現异步離線存儲。promise格式
2.localstorage僅支持字符串,存儲前、獲取後需要進行字符串序列化與反序列化,localforage可以直接存非字符串數據。

參考地址:https://www.cnblogs.com/lhb25/p/localforage-offline-storage-improved.html

// 以下nuxt.config.js配置除了TDK,其餘請自行配置,不做詳細描述

UI庫看自己喜歡。

選擇:Nuxt、typescript、Scss、axios、localforage、ElementUI

依賴

// 主要依賴
"nuxt": "^2.14.1", // 內置有很多依賴了 包括axios
"nuxt-property-decorator": "^2.7.2",
"nuxt-sass-resources-loader": "^2.0.5",
"vue-property-decorator": "^9.0.0",
"vuex-class": "^0.3.2"
"node-sass": "^4.14.1",
"sass-loader": "^9.0.2",
"@types/node": "^14.6.3",

nuxt的生命周期(及其重要,學習框架必須了解生命周期,及其原理)

在這裏插入圖片描述

基於nuxt的axios二次封裝

// plugins/axios.ts

1.與往常vue做的封裝樣子不一樣,思想也是一樣,導出ts的interface也是一樣的

import {
     AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios'
export default function ({
    $axios, redirect, app, ssrContentxt, store}: any) {
    
	const axios = $axios as AxiosInstance
}

2.請求頭的設置 (服務端與客戶端的請求頭設置是不一樣)

  • 服務端
    • /middleware/stats
    • 下列代碼只在服務端設置請求頭,但不能清除請求頭
export default function ({
     ssrContext, $axios, app }) {
    
  if (ssrContext && ssrContext.req.headers.cookie && ssrContext.req.headers.cookie.indexOf('token=') != -1) {
    
    let tmpArr = ssrContext.req.headers.cookie.split(';')
    let tokenArr = ''
    tokenArr = tmpArr.filter((value) => {
    
      return value.indexOf('token=') != -1
    })
    let cookieArr = tokenArr[0].split('token=');
    $axios.defaults.headers.token = cookieArr[1]
  } else {
    
    $axios.defaults.headers.token = ''
  }
}
  • 客戶端/plugins/axios
    因為localforage是异步的,所以用兩種方式去放入token(cookies,localforage)
 let token: any = Cookies.get('token')
 const data = value.data
 if (process.client) {
    
   if (!token) {
    
     await localforage.getItem('userInfo').then((res: any) => {
    
       if (res && res.token) {
    
         token = res.token
       }
     })
   }
   value.headers.token = token
 }

為何能够SEO優化

  • SSR
    使用asyncData、fetch、nuxtServerInit
    三者都是nuxt在服務端的hooks
	// 例子
	// axios.api與apiResult都是封裝好的
	// return是一個對象,這個對象相當於data() {return {}}  <---return出來的對象
	// 只有page有asyncData、fetch,子components是不存在hooks
	asyncData({$axios}) {
		try {
		      var homeListData: any = {
		        page: 1,
		        page_size: 4
		      }
		      const homeFileList = await app.$axios.api('homeList', homeListData) as apiResult // 首頁列錶
		      return {
		      	homeFileList: homeFileList.result
		      }
		}catch(error) {
		}
	}
	// nuxtServerInit是store的hooks
	async nuxtServerInit({commit}, {$axios}) {
	    // 獲取輪播圖
	    var data = {}
	    await app.$axios.api('homeBanner').then((res: apiResult) => {
	      if (res.code === 200) {
	        data = res.result
	      }
	    }).catch((e: any) => {
	      console.log(e)
	    })
	}
  • TDK(title、description、keywords)

  • 全局配置/nuxt.config.js

  head: {
    
    // title: process.env.npm_package_name || '',
    title: 'xxx',
    meta: [
      {
     charset: 'utf-8' },
      {
     name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
     hid: 'description', name: 'description', content: 'xxxx', keywords: 'xxxx' }
    ]
  }

CSR 和 SSR 最大的區別在於前者的頁面渲染是 JS 負責進行的,而後者是服務器端直接返回 HTML 讓瀏覽器直接渲染

使用SSR所解决的問題

1.提高SEO(搜索引擎優化)
2.提高首屏性能。

SSR渲染原理

1.簡單來說就是,掛載服務端,讓服務端去請求數據,然後去服務端去組裝html,將這個html返回到客戶端
2.總所周知,MVVM框架的模式都是基於虛擬DOM去渲染,然後通過一些方法轉化為真是DOM,掛載到瀏覽器上去。虛擬DOM其實就是JS對象形成的一顆樹。SSR所需要做的就是,MVVM打包出來的js庫,去做同構處理。所謂同構就是,瀏覽器運行一遍,服務端又運行一遍。
3.SSR的核心就是同構

為什麼要用引入node中間層

如果手寫SSR,不到萬不得已,其實不要用。它所解决最大的難點在與SEO,但同時也付出了昂貴的成本。不僅因為服務端渲染需要更加複雜的處理邏輯,還因為同構的過程需要服務端和客戶端都執行一遍代碼,這雖然對於客戶端並沒有什麼大礙,但對於服務端卻是巨大的壓力,因為數量龐大的訪問量,對於每一次訪問都要另外在服務器端執行一遍代碼進行計算和編譯,大大地消耗了服務器端的性能,成本隨之增加。如果訪問量足够大的時候,以前不用 SSR 的時候一臺服務器能够承受的壓力現在或許要增加到 10 臺才能抗住。痛點在於 SEO,但如果實際上對 SEO 要求並不高的時候,那使用 SSR 就大可不必了。

回歸問題,為什麼要引入 node 作為中間層呢?它是處在哪兩者的中間?又是解决了什麼場景下的問題?

在不用中間層的前後端分離開發模式下,前端一般直接請求後端的接口。但真實場景下,後端所給的數據格式並不是前端想要的,但處於性能原因或者其他的因素接口格式不能更改,這時候需要在前端做一些額外的數據處理操作。前端來操作數據本身無可厚非,但是當數據量變得龐大起來,那麼在客戶端就是產生巨大的性能損耗,甚至影響到用戶體驗。在這個時候,node 中間層的概念便應運而生。

它最終解决的前後端協作的問題。

一般的中間層工作流是這樣的:前端每次發送請求都是去請求 node 層的接口,然後 node 對於相應的前端請求做轉發,用 node 去請求真正的後端接口獲取數據,獲取後再由 node 層做對應的數據計算等處理操作,然後返回給前端。這就相當於讓 node 層替前端接管了對數據的操作。
在這裏插入圖片描述

使用SSR最難處理的點

  1. store
  2. 原本MVVM框架的Hooks
  3. 同構
    1. 虛擬DOM
    2. 路由
    3. store

Vue(nuxt)+typescript配置

在根目錄下創建文件vue-shim.d.ts聲明文件(其實自己創建個typing文件夾更好)

declare module "*.vue" {
    
  import Vue from 'vue'
  export default Vue
}

IDE就不會報錯了

同時還要考慮nuxt
在tsconfig.json中的配置

{
    
  "compilerOptions": {
    
    "target": "ES2018",
    "module": "esnext",
    "strict": false,
    "jsx": "preserve",
    "moduleResolution": "Node",
    "experimentalDecorators": true,
    "importHelpers": false,
    "esModuleInterop": true,
    "baseUrl": ".",
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,
    "lib": [
      "ESNext",
      "esnext.asynciterable",
      "dom",
      "dom.iterable",
      "scripthost"
    ],
    "allowJs": true,
    "sourceMap": true,
    "noEmit": true,
    "paths": {
    
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ],
      "@/components": ["./components"],
      "@/plugins": ["./plugins"]
    },
    "types": [
      "@types/node",
      "@nuxt/types"
    ]
  },
  "exclude": [
    "node_modules",
    ".nuxt",
    "dist"
  ]
}

前端安全問題

  1. xss跨站脚本攻擊原理?如何進行?防禦手段?

如何進行:如何XSS是指惡意攻擊者利用網站沒有對用戶提交數據進行轉義處理或者過濾不足的缺點,進而添加一些代碼,嵌入到web頁面中去。使別的用戶訪問都會執行相應的嵌入代碼。從而盜取用戶資料、利用用戶身份進行某種動作或者對訪問者進行病毒侵害的一種攻擊方式。

主要原理:過於信任客戶端提交的數據!

防禦手段:不信任任何客戶端提交的數據,只要是客戶端提交的數據就應該先進行相應的過濾處理然後方可進行下一步的操作。

  1. CSRF跨站請求偽造原理?如何進行?防禦手段?

如何進行:當你在某網頁登錄之後,在沒有關閉網頁的情况下,收到別人的鏈接。例如:http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=1&password_conf=1&Change=Change#

點擊鏈接,會利用瀏覽器的cookie把密碼改掉。

主要原理:在沒有關閉相關網頁的情况下,點擊其他人發來的CSRF鏈接,利用客戶端的cookie直接向服務器發送請求。

防禦手段:檢測Referer

Anti-CSRF token機制

業務上要求用戶輸入原始密碼(簡單粗暴),攻擊者在不知道原始密碼的情况下,無論如何都無法進行CSRF攻擊。

  1. Sql脚本注入原理?如何進行?防禦手段?

如何進行:利用現有應用程序,將(惡意)的SQL命令注入到後臺數據庫引擎執行的能力,它可以通過在Web錶單中輸入(惡意)SQL語句得到一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。

主要原理:通過把SQL命令插入到Web錶單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令

防禦手段:使用預編譯,綁定變量(推薦)。檢查數據類型。過濾特殊字符和語句。頁面不錯誤回顯。

  1. web上傳漏洞原理?如何進行?防禦手段?

如何進行:用戶上傳了一個可執行的脚本文件,並通過此脚本文件獲得了執行服務器端命令的能力。

主要原理:當文件上傳時沒有對文件的格式和上傳用戶做驗證,導致任意用戶可以上傳任意文件,那麼這就是一個上傳漏洞。

防禦手段:

  1. 最有效的,將文件上傳目錄直接設置為不可執行,對於Linux而言,撤銷其目錄的’x’權限;實際中很多大型網站的上傳應用都會放置在獨立的存儲上作為靜態文件處理,一是方便使用緩存加速降低能耗,二是杜絕了脚本執行的可能性;

  2. 文件類型檢查:强烈推薦白名單方式,結合MIME Type、後綴檢查等方式;此外對於圖片的處理可以使用壓縮函數或resize函數,處理圖片的同時破壞其包含的HTML代碼;

  3. 使用隨機數改寫文件名和文件路徑,使得用戶不能輕易訪問自己上傳的文件;

  4. 單獨設置文件服務器的域名

版權聲明
本文為[MatchstickMen_roukun]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/01/202201280429083303.html