亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

「Vue實(shí)踐」武裝你的前端項(xiàng)目

曹金海 / 3268人閱讀

摘要:所有的高階抽象組件是通過(guò)定義選項(xiàng)來(lái)聲明的。所以一般在生命周期或者中,需要用實(shí)例的方法清除可當(dāng)你有多個(gè)時(shí),就需要重復(fù)性勞動(dòng)銷(xiāo)毀這件事兒。更多的配置請(qǐng)看雙端開(kāi)啟開(kāi)啟壓縮的好處是什么可以減小文件體積,傳輸速度更快。

本文目錄

接口模塊處理

Vue組件動(dòng)態(tài)注冊(cè)

頁(yè)面性能調(diào)試:Hiper

Vue高階組件封裝

性能優(yōu)化:eventBus封裝

webpack插件:真香

本文項(xiàng)目基于Vue-Cli3,想知道如何正確搭建請(qǐng)看我之前的文章:

「Vue實(shí)踐」項(xiàng)目升級(jí)vue-cli3的正確姿勢(shì)

1. 接口模塊處理 1.1 axios二次封裝

這里封裝的依據(jù)是后臺(tái)傳的JWT,已封裝好的請(qǐng)?zhí)^(guò)。

import axios from "axios"
import router from "../router"
import {MessageBox, Message} from "element-ui"

let loginUrl = "/login"
// 根據(jù)環(huán)境切換接口地址
axios.defaults.baseURL = process.env.VUE_APP_API
axios.defaults.headers = {"X-Requested-With": "XMLHttpRequest"}
axios.defaults.timeout = 60000

// 請(qǐng)求攔截器
axios.interceptors.request.use(
  config => {
    if (router.history.current.path !== loginUrl) {
      let token = window.sessionStorage.getItem("token")
      if (token == null) {
        router.replace({path: loginUrl, query: {redirect: router.currentRoute.fullPath}})
        return false
      } else {
        config.headers["Authorization"] = "JWT " + token
      }
    }
    return config
  }, error => {
    Message.warning(error)
    return Promise.reject(error)
  })

緊接著的是響應(yīng)攔截器(即異常處理)

axios.interceptors.response.use(
  response => {
    return response.data
  }, error => {
    if (error.response !== undefined) {
      switch (error.response.status) {
        case 400:
          MessageBox.alert(error.response.data)
          break
        case 401:
          if (window.sessionStorage.getItem("out") === null) {
            window.sessionStorage.setItem("out", 1)
            MessageBox.confirm("會(huì)話已失效! 請(qǐng)重新登錄", "提示", {confirmButtonText: "重新登錄", cancelButtonText: "取消", type: "warning"}).then(() => {
              router.replace({path: loginUrl, query: {redirect: router.currentRoute.fullPath}})
            }).catch(action => {
              window.sessionStorage.clear()
              window.localStorage.clear()
            })
          }
          break
        case 402:
          MessageBox.confirm("登陸超時(shí) !", "提示", {confirmButtonText: "重新登錄", cancelButtonText: "取消", type: "warning"}).then(() => {
            router.replace({path: loginUrl, query: {redirect: router.currentRoute.fullPath}})
          })
          break
        case 403:
          MessageBox.alert("沒(méi)有權(quán)限!")
          break
        // ...忽略
        default:
          MessageBox.alert(`連接錯(cuò)誤${error.response.status}`)
    }
    return Promise.resolve(error.response)
  }
  return Promise.resolve(error)
})

這里做的處理分別是會(huì)話已失效和登陸超時(shí),具體的需要根據(jù)業(yè)務(wù)來(lái)作變更。

最后是導(dǎo)出基礎(chǔ)請(qǐng)求類(lèi)型封裝。

export default {
  get (url, param) {
    if (param !== undefined) {
      Object.assign(param, {_t: (new Date()).getTime()})
    } else {
      param = {_t: (new Date()).getTime()}
    }
    return axios({method: "get", url, params: param})
  },
  // 不常更新的數(shù)據(jù)用這個(gè)
  getData (url, param) {
    return axios({method: "get", url, params: param})
  },
  post (url, param, config) {
    return axios.post(url, param, config)
  },
  put: axios.put,
  _delete: axios.delete
}

其中給get請(qǐng)求加上時(shí)間戳參數(shù),避免從緩存中拿數(shù)據(jù)。 除了基礎(chǔ)請(qǐng)求類(lèi)型,還有很多類(lèi)似下載、上傳這種,需要特殊的的請(qǐng)求頭,此時(shí)可以根據(jù)自身需求進(jìn)行封裝。

瀏覽器緩存是基于url進(jìn)行緩存的,如果頁(yè)面允許緩存,則在一定時(shí)間內(nèi)(緩存時(shí)效時(shí)間前)再次訪問(wèn)相同的URL,瀏覽器就不會(huì)再次發(fā)送請(qǐng)求到服務(wù)器端,而是直接從緩存中獲取指定資源。

1.2 請(qǐng)求按模塊合并

模塊的請(qǐng)求:

import http from "@/utils/request"
export default {
  A (param) { return http.get("/api/", param) },
  B (param) { return http.post("/api/", param) }
  C (param) { return http.put("/api/", param) },
  D (param) { return http._delete("/api/", {data: param}) },
}

utils/api/index.js:

import http from "@/utils/request"
import account from "./account"
// 忽略...
const api = Object.assign({}, http, account, *...其它模塊*)
export default api
1.3 global.js中的處理

global.js中引入:

import Vue from "vue"
import api from "./api/index"
// 略...

const errorHandler = (error, vm) => {
  console.error(vm)
  console.error(error)
}

Vue.config.errorHandler = errorHandler
export default {
  install (Vue) {
    // 添加組件
    // 添加過(guò)濾器
    })
    // 全局報(bào)錯(cuò)處理
    Vue.prototype.$throw = (error) => errorHandler(error, this)
    Vue.prototype.$http = api
    // 其它配置
  }
}

寫(xiě)接口的時(shí)候就可以簡(jiǎn)化為:

async getData () {
    const params = {/*...key : value...*/}
    let res = await this.$http.A(params)
    res.code === 4000 ");$message.warning(res.msg)
}
2. 基礎(chǔ)組件自動(dòng)化全局注冊(cè)

來(lái)自 @SHERlocked93:Vue 使用中的小技巧

官方文檔:基礎(chǔ)組件的自動(dòng)化全局注冊(cè)

我們寫(xiě)組件的時(shí)候通常需要引入另外的組件:



寫(xiě)小項(xiàng)目這么引入還好,但等項(xiàng)目一臃腫起來(lái)...嘖嘖。 這里是借助webpack,使用 require.context() 方法來(lái)創(chuàng)建自己的模塊上下文,從而實(shí)現(xiàn)自動(dòng)動(dòng)態(tài)require組件。

這個(gè)方法需要3個(gè)參數(shù):

要搜索的文件夾目錄

是否還應(yīng)該搜索它的子目錄

一個(gè)匹配文件的正則表達(dá)式。

在你放基礎(chǔ)組件的文件夾根目錄下新建componentRegister.js:

import Vue from "vue"
/**
 * 首字母大寫(xiě)
 * @param str 字符串
 * @example heheHaha
 * @return {string} HeheHaha
 */
function capitalizeFirstLetter (str) {
  return str.charAt(0).toUpperCase() + str.slice(1)
}
/**
 * 對(duì)符合"xx/xx.vue"組件格式的組件取組件名
 * @param str fileName
 * @example abc/bcd/def/basicTable.vue
 * @return {string} BasicTable
 */
function validateFileName (str) {
  return /^S+.vue$/.test(str) &&
    str.replace(/^S+/(w+).vue$/, (rs, $1) => capitalizeFirstLetter($1))
}
const requireComponent = require.context("./", true, /.vue$/)
// 找到組件文件夾下以.vue命名的文件,如果文件名為index,那么取組件中的name作為注冊(cè)的組件名
requireComponent.keys().forEach(filePath => {
  const componentConfig = requireComponent(filePath)
  const fileName = validateFileName(filePath)
  const componentName = fileName.toLowerCase() === "index"
    ");

最后我們?cè)?b>main.js中

import "components/componentRegister.js"

我們就可以隨時(shí)隨地使用這些基礎(chǔ)組件,無(wú)需手動(dòng)引入了。

3. 頁(yè)面性能調(diào)試:Hiper

我們寫(xiě)單頁(yè)面應(yīng)用,想看頁(yè)面修改后性能變更其實(shí)挺繁瑣的。有時(shí)想知道是「正優(yōu)化」還是「負(fù)優(yōu)化」只能靠手動(dòng)刷新查看network。而Hiper很好解決了這一痛點(diǎn)(其實(shí)Hiper是后臺(tái)靜默運(yùn)行Chromium來(lái)實(shí)現(xiàn)無(wú)感調(diào)試)。

Hiper官方文檔

我們開(kāi)發(fā)完一個(gè)項(xiàng)目或者給一個(gè)項(xiàng)目做完性能優(yōu)化以后,如何來(lái)衡量這個(gè)項(xiàng)目的性能是否達(dá)標(biāo)?

我們的常見(jiàn)方式是在Dev Tool中的performancenetwork中看數(shù)據(jù),記錄下幾個(gè)關(guān)鍵的性能指標(biāo),然后刷新幾次再看這些性能指標(biāo)。

有時(shí)候我們發(fā)現(xiàn),由于樣本太少,受當(dāng)前「網(wǎng)絡(luò)」、「CPU」、「內(nèi)存」的繁忙程度的影響很重,有時(shí)優(yōu)化后的項(xiàng)目反而比優(yōu)化前更慢。

如果有一個(gè)工具,一次性地請(qǐng)求N次網(wǎng)頁(yè),然后把各個(gè)性能指標(biāo)取出來(lái)求平均值,我們就能非常準(zhǔn)確地知道這個(gè)優(yōu)化是「正優(yōu)化」還是「負(fù)優(yōu)化」。

并且,也可以做對(duì)比,拿到「具體優(yōu)化了多少」的準(zhǔn)確數(shù)據(jù)。這個(gè)工具就是為了解決這個(gè)痛點(diǎn)的。

全局安裝
sudo npm install hiper -g
# 或者使用 yarn:
# sudo yarn global add hiper
性能指標(biāo)
Key Value
DNS查詢(xún)耗時(shí) domainLookupEnd - domainLookupStart
TCP連接耗時(shí) connectEnd - connectStart
第一個(gè)Byte到達(dá)瀏覽器的用時(shí) responseStart - requestStart
頁(yè)面下載耗時(shí) responseEnd - responseStart
DOM Ready之后又繼續(xù)下載資源的耗時(shí) domComplete - domInteractive
白屏?xí)r間 domInteractive - navigationStart
DOM Ready 耗時(shí) domContentLoadedEventEnd - navigationStart
頁(yè)面加載總耗時(shí) loadEventEnd - navigationStart

developer.mozilla.org/zh-CN/docs/…

用例配置

 # 當(dāng)我們省略協(xié)議頭時(shí),默認(rèn)會(huì)在url前添加`https://`

 # 最簡(jiǎn)單的用法
 hiper baidu.com
 # 如何url中含有任何參數(shù),請(qǐng)使用雙引號(hào)括起來(lái)
 hiper "baidu.com");
 #  加載指定頁(yè)面100次
 hiper -n 100 "baidu.com");
 #  禁用緩存加載指定頁(yè)面100次
 hiper -n 100 "baidu.com"); --no-cache
 #  禁JavaScript加載指定頁(yè)面100次
 hiper -n 100 "baidu.com"); --no-javascript
 #  使用GUI形式加載指定頁(yè)面100次
 hiper -n 100 "baidu.com"); -H false
 #  使用指定useragent加載網(wǎng)頁(yè)100次
 hiper -n 100 "baidu.com"); -u "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"

此外,還可以配置Cookie訪問(wèn)

module.exports = {
    ....
    cookies:  [{
        name: "token",
        value: process.env.authtoken,
        domain: "example.com",
        path: "/",
        httpOnly: true
    }],
    ....
}
# 載入上述配置文件(假設(shè)配置文件在/home/下)
hiper -c /home/config.json

# 或者你也可以使用js文件作為配置文件
hiper -c /home/config.js
4. Vue高階組件封裝

我們常用的就是一個(gè)高階(抽象)組件。

export default {
  name: "keep-alive",
  abstract: true,
  ...
}

所有的高階(抽象)組件是通過(guò)定義abstract選項(xiàng)來(lái)聲明的。高階(抽象)組件不渲染真實(shí)DOM。 一個(gè)常規(guī)的抽象組件是這么寫(xiě)的:

import { xxx } from "xxx"
const A = () => {
    .....
}

export default {
    name: "xxx",
    abstract: true,
    props: ["...", "..."],
    // 生命周期鉤子函數(shù)
    created () {
      ....
    },
    ....
    destroyed () {
      ....
    },
    render() {
        const vnode = this.$slots.default
        ....
        return vnode
    },
})
4.1 防抖/節(jié)流 抽象組件

關(guān)于防抖和節(jié)流是啥就不贅述了。這里貼出組件代碼:

改編自:Vue實(shí)現(xiàn)函數(shù)防抖組件

const throttle = function(fn, wait=50, isDebounce, ctx) {
  let timer
  let lastCall = 0
  return function (...params) {
    if (isDebounce) {
      if (timer) clearTimeout(timer)
      timer = setTimeout(() => {
        fn.apply(ctx, params)
      }, wait)
    } else {
      const now = new Date().getTime()
      if (now - lastCall < wait) return
      lastCall = now
      fn.apply(ctx, params)
    }
  }
}

export default {
    name: "Throttle",
    abstract: true,
    props: {
      time: Number,
      events: String,
      isDebounce: {
        type: Boolean,
        default: false
      },
    },
    created () {
      this.eventKeys = this.events.split(",")
      this.originMap = {}
      this.throttledMap = {}
    },
    render() {
        const vnode = this.$slots.default[0]
        this.eventKeys.forEach((key) => {
            const target = vnode.data.on[key]
            if (target === this.originMap[key] && this.throttledMap[key]) {
                vnode.data.on[key] = this.throttledMap[key]
            } else if (target) {
                this.originMap[key] = target
                this.throttledMap[key] = throttle(target, this.time, this.isDebounce, vnode)
                vnode.data.on[key] = this.throttledMap[key]
            }
        })
        return vnode
    },
})

通過(guò)第三個(gè)參數(shù)isDebounce來(lái)控制切換防抖節(jié)流。 最后在main.js里引用:

import Throttle from "../Throttle"
....
Vue.component("Throttle", Throttle)
使用方式
"app"> "1000" events="click"> "1000" events="click" :isDebounce="true"> "3300" events="mouseleave" :isDebounce="true">
const app = new Vue({
    el: "#app",
    data () {
        return {
            val: 0
        }
    },
    methods: {
        onClick ($ev, val) {
            this.val += val
        },
        onAdd () {
            this.val += 3
        }
    }
})

抽象組件是一個(gè)接替Mixin實(shí)現(xiàn)抽象組件公共功能的好方法,不會(huì)因?yàn)榻M件的使用而污染DOM(添加并不想要的div標(biāo)簽等)、可以包裹任意的單一子元素等等

至于用不用抽象組件,就見(jiàn)仁見(jiàn)智了。

5. 性能優(yōu)化:eventBus封裝

中央事件總線eventBus的實(shí)質(zhì)就是創(chuàng)建一個(gè)vue實(shí)例,通過(guò)一個(gè)空的vue實(shí)例作為橋梁實(shí)現(xiàn)vue組件間的通信。它是實(shí)現(xiàn)非父子組件通信的一種解決方案。

eventBus實(shí)現(xiàn)也非常簡(jiǎn)單

import Vue from "Vue"
export default new Vue

我們?cè)谑褂弥薪?jīng)常最容易忽視,又必然不能忘記的東西,那就是:清除事件總線eventBus。

不手動(dòng)清除,它是一直會(huì)存在,這樣當(dāng)前執(zhí)行時(shí),會(huì)反復(fù)進(jìn)入到接受數(shù)據(jù)的組件內(nèi)操作獲取數(shù)據(jù),原本只執(zhí)行一次的獲取的操作將會(huì)有多次操作。本來(lái)只會(huì)觸發(fā)并只執(zhí)行一次,變成了多次,這個(gè)問(wèn)題就非常嚴(yán)重。

當(dāng)不斷進(jìn)行操作幾分鐘后,頁(yè)面就會(huì)卡頓,并占用大量?jī)?nèi)存。

所以一般在vue生命周期beforeDestroy或者destroyed中,需要用vue實(shí)例的$off方法清除eventBus

beforeDestroy(){
    bus.$off("click")
 }

可當(dāng)你有多個(gè)eventBus時(shí),就需要重復(fù)性勞動(dòng)$off銷(xiāo)毀這件事兒。 這時(shí)候封裝一個(gè) eventBus就是更優(yōu)的解決方案。

5.1 擁有生命周期的 eventBus

我們從Vue源碼Vue.init中可以得知:

 Vue.prototype._init = function (options");

每個(gè)Vue實(shí)例有自己的_uid作為唯一標(biāo)識(shí),因此我們讓EventBus_uid關(guān)聯(lián)起來(lái),并將其改造:

實(shí)現(xiàn)來(lái)自:讓在Vue中使用的EventBus也有生命周期

class EventBus {
  constructor (vue) {
    if (!this.handles) {
      Object.defineProperty(this, "handles", {
        value: {},
        enumerable: false
      })
    }
    this.Vue = vue
    // _uid和EventName的映射
    this.eventMapUid = {}
  }
  setEventMapUid (uid, eventName) {
    if (!this.eventMapUid[uid]) this.eventMapUid[uid] = []
    this.eventMapUid[uid].push(eventName) // 把每個(gè)_uid訂閱的事件名字push到各自u(píng)id所屬的數(shù)組里
  }
  $on (eventName, callback, vm) {
    // vm是在組件內(nèi)部使用時(shí)組件當(dāng)前的this用于取_uid
    if (!this.handles[eventName]) this.handles[eventName] = []
    this.handles[eventName].push(callback)
    if (vm instanceof this.Vue) this.setEventMapUid(vm._uid, eventName)
  }
  $emit () {
    let args = [...arguments]
    let eventName = args[0]
    let params = args.slice(1)
    if (this.handles[eventName]) {
      let len = this.handles[eventName].length
      for (let i = 0; i < len; i++) {
        this.handles[eventName][i](...params)
      }
    }
  }
  $offVmEvent (uid) {
    let currentEvents = this.eventMapUid[uid] || []
    currentEvents.forEach(event => {
      this.$off(event)
    })
  }
  $off (eventName) {
    delete this.handles[eventName]
  }
}
// 寫(xiě)成Vue插件形式,直接引入然后Vue.use($EventBus)進(jìn)行使用
let $EventBus = {}

$EventBus.install = (Vue, option) => {
  Vue.prototype.$eventBus = new EventBus(Vue)
  Vue.mixin({
    beforeDestroy () {
      // 攔截beforeDestroy鉤子自動(dòng)銷(xiāo)毀自身所有訂閱的事件
      this.$eventBus.$offVmEvent(this._uid) 
    }
  })
}

export default $EventBus

使用:

// main.js中
...
import EventBus from "./eventBus.js"
Vue.use(EnemtBus)
...

組件中使用:

 created () {
    let text = Array(1000000).fill("xxx").join(",")
    this.$eventBus.$on("home-on", (...args) => {
      console.log("home $on====>>>", ...args)
      this.text = text
    }, this) // 注意第三個(gè)參數(shù)需要傳當(dāng)前組件的this,如果不傳則需要手動(dòng)銷(xiāo)毀
  },
  mounted () {
    setTimeout(() => {
      this.$eventBus.$emit("home-on", "這是home $emit參數(shù)", "ee")
    }, 1000)
  },
  beforeDestroy () {
    // 這里就不需要手動(dòng)的off銷(xiāo)毀eventBus訂閱的事件了
  }
6. webpack插件:真香 6.1 取代uglifyjsTerser Plugin

在二月初項(xiàng)目升級(jí)Vue-cli3時(shí)遇到了一個(gè)問(wèn)題:uglifyjs不再支持webpack4.0。找了一圈,在Google搜索里查到Terser Plugin這個(gè)插件。

我主要用到了其中這幾個(gè)功能:

cache,啟用文件緩存。

parallel,使用多進(jìn)程并行來(lái)提高構(gòu)建速度。

sourceMap,將錯(cuò)誤消息位置映射到模塊(儲(chǔ)存著位置信息)。

drop_console,打包時(shí)剔除所有的console語(yǔ)句

drop_debugger,打包時(shí)剔除所有的debugger語(yǔ)句

作為一個(gè)管小組前端的懶B,很多時(shí)候?qū)戫?yè)面會(huì)遺留console.log,影響性能。設(shè)置個(gè)drop_console就非常香。以下配置親測(cè)有效。

const TerserPlugin = require("terser-webpack-plugin")
....
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true, // Must be set to true if using source-maps in production
terserOptions: {
  compress: {
    drop_console: true,
    drop_debugger: true
  }
}
})

更多的配置請(qǐng)看Terser Plugin

6.2 雙端開(kāi)啟 gzip

開(kāi)啟gzip壓縮的好處是什么?

可以減小文件體積,傳輸速度更快。gzip是節(jié)省帶寬和加快站點(diǎn)速度的有效方法。

服務(wù)端發(fā)送數(shù)據(jù)時(shí)可以配置 Content-Encoding:gzip,用戶(hù)說(shuō)明數(shù)據(jù)的壓縮方式

客戶(hù)端接受到數(shù)據(jù)后去檢查對(duì)應(yīng)字段的信息,就可以根據(jù)相應(yīng)的格式去解碼。

客戶(hù)端請(qǐng)求時(shí),可以用 Accept-Encoding:gzip,用戶(hù)說(shuō)明接受哪些壓縮方法。

6.2.1 Webpack開(kāi)啟gzip

這里使用的插件為:CompressionWebpackPlugin

const CompressionWebpackPlugin = require("compression-webpack-plugin")
module.exports = { 
    “plugins”:[new CompressionWebpackPlugin] 
}

具體配置:

const CompressionWebpackPlugin = require("compression-webpack-plugin");

webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: new RegExp(".(js|css)$"),
      // 只處理大于xx字節(jié) 的文件,默認(rèn):0
      threshold: 10240,
      // 示例:一個(gè)1024b大小的文件,壓縮后大小為768b,minRatio : 0.75
      minRatio: 0.8 // 默認(rèn): 0.8
      // 是否刪除源文件,默認(rèn): false
      deleteOriginalAssets: false
    })
)

開(kāi)啟gzip前

開(kāi)啟gzip后
gzip后的大小從277KB到只有~91.2KB!

6.2.2 擴(kuò)展知識(shí):Nginxgzip設(shè)置

打開(kāi)/etc/nginx/conf.d編寫(xiě)以下配置。

server {
    gzip on;
    gzip_static on;    
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_proxied  any;
    gzip_vary on;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;    
    ...
}

Nginx嘗試查找并發(fā)送文件/path/to/bundle.js.gz。如果該文件不存在,或者客戶(hù)端不支持 gzip,Nginx則會(huì)發(fā)送該文件的未壓縮版本。

保存配置后,重新啟動(dòng)Nginx:

$ sudo service nginx restart

開(kāi)啟gzip前

開(kāi)啟gzip后
6.2.3 如何驗(yàn)證gzip

通過(guò)使用curl測(cè)試每個(gè)資源的請(qǐng)求響應(yīng),并檢查Content-Encoding

顯示 Content-Encoding: gzip,即為配置成功。

6.2.4 雙端Gzip區(qū)別及其意義

不同之處在于:

    Webpack壓縮會(huì)在構(gòu)建運(yùn)行期間一次壓縮文件,然后將這些壓縮版本保存到磁盤(pán)。

    nginx在請(qǐng)求時(shí)壓縮文件時(shí),某些包可能內(nèi)置了緩存,因此性能損失只發(fā)生一次(或不經(jīng)常),但通常不同之處在于,這將在響應(yīng) HTTP請(qǐng)求時(shí)發(fā)生。

    對(duì)于實(shí)時(shí)壓縮,讓上游代理(例如 Nginx)處理 gzip和緩存通常更高效,因?yàn)樗鼈兪菍?zhuān)門(mén)為此而構(gòu)建的,并且不會(huì)遭受服務(wù)端程序運(yùn)行時(shí)的開(kāi)銷(xiāo)(許多都是用C語(yǔ)言編寫(xiě)的) 。

    使用 Webpack的好處是, Nginx每次請(qǐng)求服務(wù)端都要壓縮很久才回返回信息回來(lái),不僅服務(wù)器開(kāi)銷(xiāo)會(huì)增大很多,請(qǐng)求方也會(huì)等的不耐煩。我們?cè)?Webpack打包時(shí)就直接生成高壓縮等級(jí)的文件,作為靜態(tài)資源放在服務(wù)器上,這時(shí)將 Nginx作為二重保障就會(huì)高效很多(請(qǐng)求其它目錄資源時(shí))。

    注:具體是在請(qǐng)求時(shí)實(shí)時(shí)壓縮,或在構(gòu)建時(shí)去生成壓縮文件,就要看項(xiàng)目業(yè)務(wù)情況。

求一份深圳的內(nèi)推

本來(lái)還想謝謝動(dòng)態(tài)配置表單相關(guān),但篇幅太長(zhǎng)也太難寫(xiě)了。

好了,又水完一篇,入正題:

目前本人在(又)準(zhǔn)備跳槽,希望各位大佬和HR小姐姐可以?xún)?nèi)推一份靠譜的深圳前端崗位!996.ICU 就算了。

微信:huab119

郵箱:454274033@qq.com

作者掘金文章總集

「Vue實(shí)踐」5分鐘擼一個(gè)Vue CLI 插件

「Vue實(shí)踐」武裝你的前端項(xiàng)目

「中高級(jí)前端面試」JavaScript手寫(xiě)代碼無(wú)敵秘籍

「從源碼中學(xué)習(xí)」面試官都不知道的Vue題目答案

「從源碼中學(xué)習(xí)」Vue源碼中的JS騷操作

「從源碼中學(xué)習(xí)」徹底理解Vue選項(xiàng)Props

「Vue實(shí)踐」項(xiàng)目升級(jí)vue-cli3的正確姿勢(shì)

為何你始終理解不了JavaScript作用域鏈?

公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/7332.html

相關(guān)文章

  • 7月份前端資源分享

    摘要:更多資源請(qǐng)文章轉(zhuǎn)自月份前端資源分享的作用數(shù)組元素隨機(jī)化排序算法實(shí)現(xiàn)學(xué)習(xí)筆記數(shù)組隨機(jī)排序個(gè)變態(tài)題解析上個(gè)變態(tài)題解析下中的數(shù)字前端開(kāi)發(fā)筆記本過(guò)目不忘正則表達(dá)式聊一聊前端存儲(chǔ)那些事兒一鍵分享到各種寫(xiě)給剛?cè)腴T(mén)的前端工程師的前后端交互指南物聯(lián)網(wǎng)世界的 更多資源請(qǐng)Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://github.com/jsfr...

    pingan8787 評(píng)論0 收藏0
  • 基于 Node.js 爬蟲(chóng)的數(shù)據(jù) API,搭建一套屬于自己的 API 數(shù)據(jù)

    摘要:沒(méi)想到老師下課點(diǎn)名了,老師李。一哥們答到老師咦,李,你站起來(lái)一下這哥們低著腦袋站起來(lái)了,老師表格上面寫(xiě)的李是個(gè)女的啊這是不知道從哪個(gè)角落傳來(lái)一聲討厭啊,人家就是個(gè)女的了啦。 SpliderApi https://github.com/ecitlm/Spl... 基于nodejs 的爬蟲(chóng) API接口項(xiàng)目,包括前端開(kāi)發(fā)日?qǐng)?bào)、知乎日?qǐng)?bào)、前端top框架排行、妹紙福利、搞笑視頻/ 熱點(diǎn)新聞資訊 ...

    chenjiang3 評(píng)論0 收藏0
  • 前端開(kāi)發(fā)-從入門(mén)到Offer - 收藏集 - 掘金

    摘要:一些知識(shí)點(diǎn)有哪些方法方法前端從入門(mén)菜鳥(niǎo)到實(shí)踐老司機(jī)所需要的資料與指南合集前端掘金前端從入門(mén)菜鳥(niǎo)到實(shí)踐老司機(jī)所需要的資料與指南合集歸屬于筆者的前端入門(mén)與最佳實(shí)踐。 工欲善其事必先利其器-前端實(shí)習(xí)簡(jiǎn)歷篇 - 掘金 有幸認(rèn)識(shí)很多在大廠工作的學(xué)長(zhǎng),在春招正式開(kāi)始前為我提供很多內(nèi)部推薦的機(jī)會(huì),非常感謝他們對(duì)我的幫助?,F(xiàn)在就要去北京了,對(duì)第一份正式的實(shí)習(xí)工作也充滿(mǎn)期待,也希望把自己遇到的一些問(wèn)題和...

    sf_wangchong 評(píng)論0 收藏0
  • 將函數(shù)式進(jìn)行到底,用 Hooks 武裝組件 - TXD 前端月刊 201905 期

    摘要:一個(gè)合格的中級(jí)前端工程師必須要掌握的個(gè)技巧對(duì)在畢業(yè)季還在找工作的同學(xué),可以說(shuō)很實(shí)用的,如果能全部掌握這些技巧,拿到幾個(gè)應(yīng)該是沒(méi)有問(wèn)題的,當(dāng)然要注意平時(shí)的積累,能力要全面。而且該托管服務(wù)是完全免費(fèi)的。 showImg(https://segmentfault.com/img/remote/1460000019376228?w=1790&h=898); 【阿里云 TXD 前端月刊】- 熱門(mén)...

    xi4oh4o 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<