主頁 > 企業開發 > Webpack 4 Tree Shaking 終極優化指南

Webpack 4 Tree Shaking 終極優化指南

2020-10-13 20:26:52 企業開發

幾個月前,我的任務是將我們組的 Vue.js 專案構建配置升級到 Webpack 4,我們的主要目標之一是利用 tree-shaking 的優勢,即 Webpack 去掉了實際上并沒有使用的代碼來減少包的大小,現在,tree-shaking 的好處將根據你的代碼庫而有所不同,由于我們的幾個架構決策,我們從公司內部的其他庫中提取了大量代碼,而我們只使用了其中的一小部分,

我寫這篇文章是因為恰當地優化 Webpack 并不簡單,一開始我以為這是一種簡單的魔法,但后來我花了一個月的時間在網上搜索我遇到的一系列問題的答案,我希望通過這篇文章,其他人會更容易地處理類似問題,

先說好處

在討論技術細節之前,讓我先總結一下好處,不同的應用程式將看到不同程度的好處,主要的決定因素是應用程式中死代碼的數量,如果你沒有多少死代碼,那么你就看不到 tree-shaking 的多少好處,我們專案里有很多死代碼,

在我們部門,最大的問題是共享庫的數量,從簡單的自定義組件庫,到企業標準組件庫,再到莫名其妙地塞到一個庫中的大量代碼,很多都是技術債務,但一個大問題是我們所有的應用程式都在匯入所有這些庫,而實際上每個應用程式都只需要其中的一小部分

總的來說,一旦實作了 tree-shaking,我們的應用程式就會根據應用程式的不同,縮減率從25%到75%,平均縮減率為52%,主要是由這些龐大的共享庫驅動的,它們是小型應用程式中的主要代碼,

同樣,具體情況會有所不同,但是如果你覺得你打的包中可能有很多不需要的代碼,這就是如何消除它們的方法,

沒有示例代碼倉庫

對不住了各位老鐵,我做的專案是公司的財產,所以我不能分享代碼到 GitHub 倉庫了,但是,我將在本文中提供簡化的代碼示例來說明我的觀點,

因此,廢話少說,讓我們來看看如何撰寫可實作 tree-shaking 的最佳 webpack 4 配置,

什么是死代碼

很簡單:就是 Webpack 沒看到你使用的代碼,Webpack 跟蹤整個應用程式的 import/export 陳述句,因此,如果它看到匯入的東西最終沒有被使用,它會認為那是“死代碼”,并會對其進行 tree-shaking ,

死代碼并不總是那么明確的,下面是一些死代碼和“活”代碼的例子,希望能讓你更明白,請記住,在某些情況下,Webpack 會將某些東西視為死代碼,盡管它實際上并不是,請參閱《副作用》一節,了解如何處理,

// 匯入并賦值給 JavaScript 物件,然后在下面的代碼中被用到
// 這會被看作“活”代碼,不會做 tree-shaking
import Stuff from './stuff';
doSomething(Stuff);
// 匯入并賦值給 JavaScript 物件,但在接下來的代碼里沒有用到
// 這就會被當做“死”代碼,會被 tree-shaking
import Stuff from './stuff';
doSomething();
// 匯入但沒有賦值給 JavaScript 物件,也沒有在代碼里用到
// 這會被當做“死”代碼,會被 tree-shaking
import './stuff';
doSomething();
// 匯入整個庫,但是沒有賦值給 JavaScript 物件,也沒有在代碼里用到
// 非常奇怪,這竟然被當做“活”代碼,因為 Webpack 對庫的匯入和本地代碼匯入的處理方式不同,
import 'my-lib';
doSomething();

用支持 tree-shaking 的方式寫 import

在撰寫支持 tree-shaking 的代碼時,匯入方式非常重要,你應該避免將整個庫匯入到單個 JavaScript 物件中,當你這樣做時,你是在告訴 Webpack 你需要整個庫, Webpack 就不會搖它,

以流行的庫 Lodash 為例,一次匯入整個庫是一個很大的錯誤,但是匯入單個的模塊要好得多,當然,Lodash 還需要其他的步驟來做 tree-shaking,但這是個很好的起點,

// 全部匯入 (不支持 tree-shaking)
import _ from 'lodash';
// 具名匯入(支持 tree-shaking)
import { debounce } from 'lodash';
// 直接匯入具體的模塊 (支持 tree-shaking)
import debounce from 'lodash/lib/debounce';

基本的 Webpack 配置

使用 Webpack 進行 tree-shaking 的第一步是撰寫 Webpack 組態檔,你可以對你的 webpack 做很多自定義配置,但是如果你想要對代碼進行 tree-shaking,就需要以下幾項,

首先,你必須處于生產模式,Webpack 只有在壓縮代碼的時候會 tree-shaking,而這只會發生在生產模式中,

其次,必須將優化選項 “usedExports” 設定為true,這意味著 Webpack 將識別出它認為沒有被使用的代碼,并在最初的打包步驟中給它做標記,

最后,你需要使用一個支持洗掉死代碼的壓縮器,這種壓縮器將識別出 Webpack 是如何標記它認為沒有被使用的代碼,并將其剝離,TerserPlugin 支持這個功能,推薦使用,

下面是 Webpack 開啟 tree-shaking 的基本配置:

// Base Webpack Config for Tree Shaking
const config = {
 mode: 'production',
 optimization: {
  usedExports: true,
  minimizer: [
   new TerserPlugin({...})
  ]
 }
};

有什么副作用

僅僅因為 Webpack 看不到一段正在使用的代碼,并不意味著它可以安全地進行 tree-shaking,有些模塊匯入,只要被引入,就會對應用程式產生重要的影響,一個很好的例子就是全域樣式表,或者設定全域配置的JavaScript 檔案,

Webpack 認為這樣的檔案有“副作用”,具有副作用的檔案不應該做 tree-shaking,因為這將破壞整個應用程式,Webpack 的設計者清楚地認識到不知道哪些檔案有副作用的情況下打包代碼的風險,因此默認地將所有代碼視為有副作用,這可以保護你免于洗掉必要的檔案,但這意味著 Webpack 的默認行為實際上是不進行 tree-shaking,

幸運的是,我們可以配置我們的專案,告訴 Webpack 它是沒有副作用的,可以進行 tree-shaking,

如何告訴 Webpack 你的代碼無副作用

package.json 有一個特殊的屬性 sideEffects,就是為此而存在的,它有三個可能的值:

true 是默認值,如果不指定其他值的話,這意味著所有的檔案都有副作用,也就是沒有一個檔案可以 tree-shaking,

false 告訴 Webpack 沒有檔案有副作用,所有檔案都可以 tree-shaking,

第三個值 […] 是檔案路徑陣列,它告訴 webpack,除了陣列中包含的檔案外,你的任何檔案都沒有副作用,因此,除了指定的檔案之外,其他檔案都可以安全地進行 tree-shaking,

每個專案都必須將 sideEffects 屬性設定為 false 或檔案路徑陣列,在我公司的作業中,我們的基本應用程式和我提到的所有共享庫都需要正確配置 sideEffects 標志,

下面是 sideEffects 標志的一些代碼示例,盡管有 JavaScript 注釋,但這是 JSON 代碼:

// 所有檔案都有副作用,全都不可 tree-shaking
{
 "sideEffects": true
}
// 沒有檔案有副作用,全都可以 tree-shaking
{
 "sideEffects": false
}
// 只有這些檔案有副作用,所有其他檔案都可以 tree-shaking,但會保留這些檔案
{
 "sideEffects": [
  "./src/file1.js",
  "./src/file2.js"
 ]
}

全域 CSS 與副作用

首先,讓我們在這個背景關系中定義全域 CSS,全域 CSS 是直接匯入到 JavaScript 檔案中的樣式表(可以是CSS、SCSS等),它沒有被轉換成 CSS 模塊或任何類似的東西,基本上,import 陳述句是這樣的:

// 匯入全域 CSS
import './MyStylesheet.css';

因此,如果你做了上面提到的副作用更改,那么在運行 webpack 構建時,你將立即注意到一個棘手的問題,以上述方式匯入的任何樣式表現在都將從輸出中洗掉,這是因為這樣的匯入被 webpack 視為死代碼,并被洗掉,

幸運的是,有一個簡單的解決方案可以解決這個問題,Webpack 使用它的模塊規則系統來控制各種型別檔案的加載,每種檔案型別的每個規則都有自己的 sideEffects 標志,這會覆寫之前為匹配規則的檔案設定的所有 sideEffects 標志,

所以,為了保留全域 CSS 檔案,我們只需要設定這個特殊的 sideEffects 標志為 true,就像這樣:

// 全域 CSS 副作用規則相關的 Webpack 配置
const config = {
 module: {
  rules: [
   {
    test: /regex/,
    use: [loaders],
    sideEffects: true
   }
  ]
 } 
};

Webpack 的所有模塊規則上都有這個屬性,處理全域樣式表的規則必須用上它,包括但不限于 CSS/SCSS/LESS/等等,

什么是模塊,模塊為什么重要

現在我們開始進入秘境,表面上看,編譯出正確的模塊型別似乎是一個簡單的步驟,但是正如下面幾節將要解釋的,這是一個會導致許多復雜問題的領域,這是我花了很長時間才弄明白的部分,

首先,我們需要了解一下模塊,多年來,JavaScript 已經發展出了在檔案之間以“模塊”的形式有效匯入/匯出代碼的能力,有許多不同的 JavaScript 模塊標準已經存在了多年,但是為了本文的目的,我們將重點關注兩個標準,一個是 “commonjs”,另一個是 “es2015”,下面是它們的代碼形式:

// Commonjs
const stuff = require('./stuff');
module.exports = stuff;

// es2015 
import stuff from './stuff';
export default stuff;

默認情況下,Babel 假定我們使用 es2015 模塊撰寫代碼,并轉換 JavaScript 代碼以使用 commonjs 模塊,這樣做是為了與服務器端 JavaScript 庫的廣泛兼容性,這些 JavaScript 庫通常構建在 NodeJS 之上(NodeJS 只支持 commonjs 模塊),但是,Webpack 不支持使用 commonjs 模塊來完成 tree-shaking,

現在,有一些插件(如 common-shake-plugin)聲稱可以讓 Webpack 有能力對 commonjs 模塊進行 tree-shaking,但根據我的經驗,這些插件要么不起作用,要么在 es2015 模塊上運行時,對 tree-shaking 的影響微乎其微,我不推薦這些插件,

因此,為了進行 tree-shaking,我們需要將代碼編譯到 es2015 模塊,

es2015 模塊 Babel 配置

據我所知,Babel 不支持將其他模塊系統編譯成 es2015 模塊,但是,如果你是前端開發人員,那么你可能已經在使用 es2015 模塊撰寫代碼了,因為這是全面推薦的方法,

因此,為了讓我們編譯的代碼使用 es2015 模塊,我們需要做的就是告訴 babel 不要管它們,為了實作這一點,我們只需將以下內容添加到我們的 babel.config.js 中(在本文中,你會看到我更喜歡JavaScript 配置而不是 JSON 配置):

// es2015 模塊的基本 Babel 配置
const config = {
 presets: [
  [
   '[@babel/preset-env](http://twitter.com/babel/preset-env)',
   {
    modules: false
   }
  ]
 ]
};

modules 設定為 false,就是告訴 babel 不要編譯模塊代碼,這會讓 Babel 保留我們現有的 es2015 import/export 陳述句,

劃重點:所有可需要 tree-shaking 的代碼必須以這種方式編譯,因此,如果你有要匯入的庫,則必須將這些庫編譯為 es2015 模塊以便進行 tree-shaking ,如果它們被編譯為 commonjs,那么它們就不能做 tree-shaking ,并且將會被打包進你的應用程式中,許多庫支持部分匯入,lodash 就是一個很好的例子,它本身是 commonjs 模塊,但是它有一個 lodash-es 版本,用的是 es2015模塊,

此外,如果你在應用程式中使用內部庫,也必須使用 es2015 模塊編譯,為了減少應用程式包的大小,必須將所有這些內部庫修改為以這種方式編譯,

不好意思, Jest 罷工了

其他測驗框架情況類似,我們用的是 Jest,

不管怎么樣,如果你走到了這一步,你會發現 Jest 測驗開始失敗了,你會像我當時一樣,看到日志里出現各種奇怪的錯誤,慌的一批,別慌,我會帶你一步一步解決,

出現這個結果的原因很簡單:NodeJS,Jest 是基于 NodeJS 開發的,而 NodeJS 不支持 es2015 模塊,為此有一些方法可以配置 Node,但是在 jest 上行不通,因此,我們卡在這里了:Webpack 需要 es2015 進行 tree shaking,但是 Jest 無法在這些模塊上執行測驗,

就是為什么我說進入了模塊系統的“秘境”,這是整個程序中耗費我最多時間來搞清楚的部分,建議你仔細閱讀這一節和后面幾節,因為我會給出解決方案,

解決方案有兩個主要部分,第一部分針對專案本身的代碼,也就是跑測驗的代碼,這部分比較容易,第二部分針對庫代碼,也就是來自其他專案,被編譯成 es2015 模塊并引入到當前專案的代碼,這部分比較復雜,

解決專案本地 Jest 代碼

針對我們的問題,babel 有一個很有用的特性:環境選項,通過配置可以運行在不同環境,在這里,開發和生產環境我們需要 es2015 模塊,而測驗環境需要 commonjs 模塊,還好,Babel 配置起來非常容易:

// 分環境配置Babel 
const config = {
 env: {
  development: {
   presets: [
    [
     '[@babel/preset-env](http://twitter.com/babel/preset-env)',
     {
      modules: false
     }
    ]
   ]
  },
  production: {
   presets: [
    [
     '[@babel/preset-env](http://twitter.com/babel/preset-env)',
     {
      modules: false
     }
    ]
   ]
  },
  test: {
   presets: [
    [
     '[@babel/preset-env](http://twitter.com/babel/preset-env)',
     {
      modules: 'commonjs'
     }
    ]
   ],
   plugins: [
    'transform-es2015-modules-commonjs' // Not sure this is required, but I had added it anyway
   ]
  }
 }
};

設定好之后,所有的專案本地代碼能夠正常編譯,Jest 測驗能運行了,但是,使用 es2015 模塊的第三方庫代碼依然不能運行,

解決 Jest 中的庫代碼

庫代碼運行出錯的原因非常明顯,看一眼node_modules 目錄就明白了,這里的庫代碼用的是 es2015 模塊語法,為了進行 tree-shaking,這些庫已經采用這種方式編譯過了,因此當 Jest 在單元測驗中試圖讀取這些代碼時,就炸了,注意到沒有,我們已經讓 Babel 在測驗環境中啟用 commonjs 模塊了呀,為什么對這些庫不起作用呢?這是因為,Jest (尤其是 babel-jest) 在跑測驗之前編譯代碼的時候,默認忽略任何來自node_modules 的代碼,

這實際上是件好事,如果 Jest 需要重新編譯所有庫的話,將會大大增加測驗處理時間,然而,雖然我們不想讓它重新編譯所有代碼,但我們希望它重新編譯使用 es2015 模塊的庫,這樣才能在單元測驗里使用,

幸好,Jest 在它的配置中為我們提供了解決方案,我想說,這部分確實讓我想了很久,并且我感覺沒必要搞得這么復雜,但這是我能想到的唯一解決方案,

配置 Jest 重新編譯庫代碼

// 重新編譯庫代碼的 Jest 配置 
const path = require('path');
const librariesToRecompile = [
 'Library1',
 'Library2'
].join('|');
const config = {
 transformIgnorePatterns: [
  `[\\\/]node_modules[\\\/](?!(${librariesToRecompile})).*$`
 ],
 transform: {
  '^.+\.jsx?$': path.resolve(__dirname, 'transformer.js')
 }
};

以上配置是 Jest 重新編譯你的庫所需要的,有兩個主要部分,我會一一解釋,

transformIgnorePatterns 是 Jest 配置的一個功能,它是一個正則字串陣列,任何匹配這些正則運算式的代碼,都不會被 babel-jest 重新編譯,默認是一個字串“node_modules”,這就是為什么Jest 不會重新編譯任何庫代碼,

當我們提供了自定義配置,就是告訴 Jest 重新編譯的時候如何忽略代碼,也就是為什么你剛才看到的變態的正則運算式有一個負向先行斷言在里面,目的是為了匹配除了庫以外的所有代碼,換句話說,我們告訴 Jest 忽略 node_modules 中除了指定庫之外的所有代碼,

這又一次證明了 JavaScript 配置比 JSON 配置要好,因為我可以輕松地通過字串操作,往正則運算式里插入庫名字的陣列拼接,

第二個是 transform 配置,他指向一個自定義的 babel-jest 轉換器,我不敢100%確定這個是必須的,但我還是加上了,設定它用于在重新編譯所有代碼時加載我們的 Babel 配置,

// Babel-Jest 轉換器
const babelJest = require('babel-jest');
const path = require('path');
const cwd = process.cwd();
const babelConfig = require(path.resolve(cwd, 'babel.config'));
module.exports = babelJest.createTransformer(babelConfig);

這些都配置好后,你在測驗代碼應該又能跑了,記住了,任何使用庫的 es2015 模塊都需要這樣配置,不然測驗代碼跑不動,

接下來輪到另一個痛點了:鏈接庫,使用 npm/yarn 鏈接的程序就是創建一個指向本地專案目錄的符號鏈接,結果表明,Babel 在重新編譯通過這種方式鏈接的庫時,會拋出很多錯誤,我之所以花了這么長時間才弄清楚 Jest 這檔子事兒,原因之一就是我一直通過這種方式鏈接我的庫,出現了一堆錯誤,

解決辦法就是:不要使用 npm/yarn link,用類似 “yalc” 這樣的工具,它可以連接本地專案,同時能模擬正常的 npm 安裝程序,它不但沒有 Babel 重編譯的問題,還能更好地處理傳遞性依賴,

針對特定庫的優化,

如果完成了以上所有步驟,你的應用基本上實作了比較健壯的 tree shaking,不過,為了進一步減少檔案包大小,你還可以做一些事情,我會列舉一些特定庫的優化方法,但這絕對不是全部,它尤其能為我們提供靈感,做出一些更酷的事情,

MomentJS 是出了名的大體積庫,幸好它可以剔除多語言包來減少體積,在下面的代碼示例中,我排除了 momentjs 所有的多語言包,只保留了基本部分,體積明顯小了很多,

// 用 IgnorePlugin 移除多語言包
const { IgnorePlugin } from 'webpack';
const config = {
 plugins: [
  new IgnorePlugin(/^\.\/locale$/, /moment/)
 ]
};

Moment-Timezone 是 MomentJS 的老表,也是個大塊頭,它的體積基本上是一個帶有時區資訊的超大 JSON 檔案導致的,我發現只要保留本世紀的年份資料,就可以將體積縮小90%,這種情況需要用到一個特殊的 Webpack 插件,

// MomentTimezone Webpack Plugin
const MomentTimezoneDataPlugin = require('moment-timezone-data-webpack-plugin');
const config = {
 plugins: [
  new MomentTimezoneDataPlugin({
   startYear: 2018,
   endYear: 2100
  })
 ]
};

Lodash 是另一個導致檔案包膨脹的大塊頭,幸好有一個替代包 Lodash-es,它被編譯成 es2015 模塊,并帶有 sideEffects 標志,用它替換 Lodash 可以進一步縮減包的大小,

另外,Lodash-es,react-bootstrap 以及其他庫可以在 Babel transform imports 插件的幫助下實作瘦身,該插件從庫的 index.js 檔案讀取 import 陳述句,并使其指向庫中特定檔案,這樣就使 webpack 在決議模塊樹時更容易對庫做 tree shaking,下面的例子演示了它是如何作業的,

// Babel Transform Imports
// Babel config
const config = {
 plugins: [
  [
   'transform-imports',
   {
    'lodash-es': {
     transform: 'lodash/${member}',
     preventFullImport: true
    },
    'react-bootstrap': {
     transform: 'react-bootstrap/es/${member}', // The es folder contains es2015 module versions of the files
     preventFullImport: true
    }
   }
  ]
 ]
};
// 這些庫不再支持全量匯入,否則會報錯
import _ from 'lodash-es';
// 具名匯入依然支持
import { debounce } from 'loash-es';
// 不過這些具名匯入會被babel編譯成這樣子
// import debounce from 'lodash-es/debounce';

總結

全文到此結束,這樣的優化可以極大地縮減打包后的大小,隨著前端架構開始有了新的方向(比如微前端),保持包大小最優化變得比以往更加重要,希望本文能給那些正在給應用程式做tree shaking的同學帶來一些幫助,

交流

歡迎掃碼關注微信公眾號“1024譯站”,為你奉上更多技術干貨,
公眾號:1024譯站

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/171269.html

標籤:JavaScript

上一篇:巧妙利用參考,將陣列轉換成樹形陣列

下一篇:一、VUE基礎回顧1

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more