最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談webpack 構(gòu)建性能優(yōu)化策略小結(jié)

 更新時間:2018年06月13日 09:41:11   作者:AMIGO_GO  
webpack以其豐富的功能和靈活的配置而深受業(yè)內(nèi)吹捧,逐步取代了grunt和gulp成為大多數(shù)前端工程實踐中的首選,這篇文章主要介紹了淺談webpack 構(gòu)建性能優(yōu)化策略小結(jié),感興趣的小伙伴們可以參考一下

背景

如今前端工程化的概念早已經(jīng)深入人心,選擇一款合適的編譯和資源管理工具已經(jīng)成為了所有前端工程中的標(biāo)配,而在諸多的構(gòu)建工具中,webpack以其豐富的功能和靈活的配置而深受業(yè)內(nèi)吹捧,逐步取代了grunt和gulp成為大多數(shù)前端工程實踐中的首選,React,Vue,Angular等諸多知名項目也都相繼選用其作為官方構(gòu)建工具,極受業(yè)內(nèi)追捧。但是,隨者工程開發(fā)的復(fù)雜程度和代碼規(guī)模不斷地增加,webpack暴露出來的各種性能問題也愈發(fā)明顯,極大的影響著開發(fā)過程中的體驗。

問題歸納

歷經(jīng)了多個web項目的實戰(zhàn)檢驗,我們對webapck在構(gòu)建中逐步暴露出來的性能問題歸納主要有如下幾個方面:

  • 代碼全量構(gòu)建速度過慢,即使是很小的改動,也要等待長時間才能查看到更新與編譯后的結(jié)果(引入HMR熱更新后有明顯改進);
  • 隨著項目業(yè)務(wù)的復(fù)雜度增加,工程模塊的體積也會急劇增大,構(gòu)建后的模塊通常要以M為單位計算;
  • 多個項目之間共用基礎(chǔ)資源存在重復(fù)打包,基礎(chǔ)庫代碼復(fù)用率不高;
  • node的單進程實現(xiàn)在耗cpu計算型loader中表現(xiàn)不佳;

針對以上的問題,我們來看看怎樣利用webpack現(xiàn)有的一些機制和第三方擴展插件來逐個擊破。

慢在何處

作為工程師,我們一直鼓勵要理性思考,用數(shù)據(jù)和事實說話,“我覺得很慢”,“太卡了”,“太大了”之類的表述難免顯得太籠統(tǒng)和太抽象,那么我們不妨從如下幾個方面來著手進行分析:


  • 從項目結(jié)構(gòu)著手,代碼組織是否合理,依賴使用是否合理;
  • 從webpack自身提供的優(yōu)化手段著手,看看哪些api未做優(yōu)化配置;
  • 從webpack自身的不足著手,做有針對性的擴展優(yōu)化,進一步提升效率;

在這里我們推薦使用一個wepback的可視化資源分析工具:webpack-bundle-analyzer,在webpack構(gòu)建的時候會自動幫你計算出各個模塊在你的項目工程中的依賴與分布情況,方便做更精確的資源依賴和引用的分析。

從上圖中我們不難發(fā)現(xiàn)大多數(shù)的工程項目中,依賴庫的體積永遠是大頭,通常體積可以占據(jù)整個工程項目的7-9成,而且在每次開發(fā)過程中也會重新讀取和編譯對應(yīng)的依賴資源,這其實是很大的的資源開銷浪費,而且對編譯結(jié)果影響微乎其微,畢竟在實際業(yè)務(wù)開發(fā)中,我們很少會去主動修改第三方庫中的源碼,改進方案如下:

方案一、合理配置 CommonsChunkPlugin

webpack的資源入口通常是以entry為單元進行編譯提取,那么當(dāng)多entry共存的時候,CommonsChunkPlugin的作用就會發(fā)揮出來,對所有依賴的chunk進行公共部分的提取,但是在這里可能很多人會誤認為抽取公共部分指的是能抽取某個代碼片段,其實并非如此,它是以module為單位進行提取。

假設(shè)我們的頁面中存在entry1,entry2,entry3三個入口,這些入口中可能都會引用如utils,loadash,fetch等這些通用模塊,那么就可以考慮對這部分的共用部分機提取。通常提取方式有如下四種實現(xiàn):

1、傳入字符串參數(shù),由chunkplugin自動計算提取

new webpack.optimize.CommonsChunkPlugin('common.js')

這種做法默認會把所有入口節(jié)點的公共代碼提取出來, 生成一個common.js

2、有選擇的提取公共代碼

new webpack.optimize.CommonsChunkPlugin('common.js',['entry1','entry2']);

只提取entry1節(jié)點和entry2中的共用部分模塊, 生成一個common.js

3、將entry下所有的模塊的公共部分(可指定引用次數(shù))提取到一個通用的chunk中

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendors',
  minChunks: function (module, count) {
    return (
     module.resource &&
     /\.js$/.test(module.resource) &&
     module.resource.indexOf(
      path.join(__dirname, '../node_modules')
     ) === 0
    )
  }
});

提取所有node_modules中的模塊至vendors中,也可以指定minChunks中的最小引用數(shù);

4、抽取enry中的一些lib抽取到vendors中

entry = {
  vendors: ['fetch', 'loadash']
};
new webpack.optimize.CommonsChunkPlugin({
  name: "vendors",
  minChunks: Infinity
});

添加一個entry名叫為vendors,并把vendors設(shè)置為所需要的資源庫,CommonsChunk會自動提取指定庫至vendors中。

方案二、通過 externals 配置來提取常用庫

在實際項目開發(fā)過程中,我們并不需要實時調(diào)試各種庫的源碼,這時候就可以考慮使用external選項了。

簡單來說external就是把我們的依賴資源聲明為一個外部依賴,然后通過script外鏈腳本引入。這也是我們早期頁面開發(fā)中資源引入的一種翻版,只是通過配置后可以告知webapck遇到此類變量名時就可以不用解析和編譯至模塊的內(nèi)部文件中,而改用從外部變量中讀取,這樣能極大的提升編譯速度,同時也能更好的利用CDN來實現(xiàn)緩存。

external的配置相對比較簡單,只需要完成如下三步:

1、在頁面中加入需要引入的lib地址,如下:

<head>
<script src="http://cdn.bootcss.com/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/underscore.min.js"></script>
<script src="/static/common/react.min.js"></script>
<script src="/static/common/react-dom.js"></script>
<script src="/static/common/react-router.js"></script>
<script src="/static/common/immutable.js"></script>
</head>

2、在webapck.config.js中加入external配置項:

module.export = {
  externals: {
    'react-router': {
      amd: 'react-router',
      root: 'ReactRouter',
      commonjs: 'react-router',
      commonjs2: 'react-router'
    },
    react: {
      amd: 'react',
      root: 'React',
      commonjs: 'react',
      commonjs2: 'react'
    },
    'react-dom': {
      amd: 'react-dom',
      root: 'ReactDOM',
      commonjs: 'react-dom',
      commonjs2: 'react-dom'
    }
  }
}

這里要提到的一個細節(jié)是:此類文件在配置前,構(gòu)建這些資源包時需要采用amd/commonjs/cmd相關(guān)的模塊化進行兼容封裝,即打包好的庫已經(jīng)是umd模式包裝過的,如在node_modules/react-router中我們可以看到umd/ReactRouter.js之類的文件,只有這樣webpack中的require和import * from 'xxxx'才能正確讀到該類包的引用,在這類js的頭部一般也能看到如下字樣:

if (typeof exports === 'object' && typeof module === 'object') {
  module.exports = factory(require("react"));
} else if (typeof define === 'function' && define.amd) {
  define(["react"], factory);
} else if (typeof exports === 'object') {
  exports["ReactRouter"] = factory(require("react"));
} else {
  root["ReactRouter"] = factory(root["React"]);
}

3、非常重要的是一定要在output選項中加入如下一句話:

output: {
 libraryTarget: 'umd'
}

由于通過external提取過的js模塊是不會被記錄到webapck的chunk信息中,通過libraryTarget可告知我們構(gòu)建出來的業(yè)務(wù)模塊,當(dāng)讀到了externals中的key時,需要以umd的方式去獲取資源名,否則會有出現(xiàn)找不到module的情況。

通過配置后,我們可以看到對應(yīng)的資源信息已經(jīng)可以在瀏覽器的source map中讀到了。

對應(yīng)的資源也可以直接由頁面外鏈載入,有效地減小了資源包的體積。

方案三、利用 DllPlugin 和 DllReferencePlugin 預(yù)編譯資源模塊

我們的項目依賴中通常會引用大量的npm包,而這些包在正常的開發(fā)過程中并不會進行修改,但是在每一次構(gòu)建過程中卻需要反復(fù)的將其解析,如何來規(guī)避此類損耗呢?這兩個插件就是干這個用的。

簡單來說DllPlugin的作用是預(yù)先編譯一些模塊,而DllReferencePlugin則是把這些預(yù)先編譯好的模塊引用起來。這邊需要注意的是DllPlugin必須要在DllReferencePlugin執(zhí)行前先執(zhí)行一次,dll這個概念應(yīng)該也是借鑒了windows程序開發(fā)中的dll文件的設(shè)計理念。

相對于externals,dllPlugin有如下幾點優(yōu)勢:

  1. dll預(yù)編譯出來的模塊可以作為靜態(tài)資源鏈接庫可被重復(fù)使用,尤其適合多個項目之間的資源共享,如同一個站點pc和手機版等;
  2. dll資源能有效地解決資源循環(huán)依賴的問題,部分依賴庫如:react-addons-css-transition-group這種原先從react核心庫中抽取的資源包,整個代碼只有一句話:
module.exports = require('react/lib/ReactCSSTransitionGroup');

卻因為重新指向了react/lib中,這也會導(dǎo)致在通過externals引入的資源只能識別react,尋址解析react/lib則會出現(xiàn)無法被正確索引的情況。

由于externals的配置項需要對每個依賴庫進行逐個定制,所以每次增加一個組件都需要手動修改,略微繁瑣,而通過dllPlugin則能完全通過配置讀取,減少維護的成本;

1、配置dllPlugin對應(yīng)資源表并編譯文件

那么externals該如何使用呢,其實只需要增加一個配置文件:webpack.dll.config.js:

const webpack = require('webpack');
const path = require('path');
const isDebug = process.env.NODE_ENV === 'development';
const outputPath = isDebug ? path.join(__dirname, '../common/debug') : path.join(__dirname, '../common/dist');
const fileName = '[name].js';

// 資源依賴包,提前編譯
const lib = [
 'react',
 'react-dom',
 'react-router',
 'history',
 'react-addons-pure-render-mixin',
 'react-addons-css-transition-group',
 'redux',
 'react-redux',
 'react-router-redux',
 'redux-actions',
 'redux-thunk',
 'immutable',
 'whatwg-fetch',
 'byted-people-react-select',
 'byted-people-reqwest'
];

const plugin = [
 new webpack.DllPlugin({
  /**
   * path
   * 定義 manifest 文件生成的位置
   * [name]的部分由entry的名字替換
   */
  path: path.join(outputPath, 'manifest.json'),
  /**
   * name
   * dll bundle 輸出到那個全局變量上
   * 和 output.library 一樣即可。
   */
  name: '[name]',
  context: __dirname
 }),
 new webpack.optimize.OccurenceOrderPlugin()
];

if (!isDebug) {
 plugin.push(
  new webpack.DefinePlugin({
   'process.env.NODE_ENV': JSON.stringify('production')
  }),
  new webpack.optimize.UglifyJsPlugin({
   mangle: {
    except: ['$', 'exports', 'require']
   },
   compress: { warnings: false },
   output: { comments: false }
  })
 )
}

module.exports = {
 devtool: '#source-map',
 entry: {
  lib: lib
 },
 output: {
  path: outputPath,
  filename: fileName,
  /**
   * output.library
   * 將會定義為 window.${output.library}
   * 在這次的例子中,將會定義為`window.vendor_library`
   */
  library: '[name]',
  libraryTarget: 'umd',
  umdNamedDefine: true
 },
 plugins: plugin
};

然后執(zhí)行命令:

$ NODE_ENV=development webpack --config webpack.dll.lib.js --progress
$ NODE_ENV=production webpack --config webpack.dll.lib.js --progress 

即可分別編譯出支持調(diào)試版和生產(chǎn)環(huán)境中l(wèi)ib靜態(tài)資源庫,在構(gòu)建出來的文件中我們也可以看到會自動生成如下資源:

common
├── debug
│  ├── lib.js
│  ├── lib.js.map
│  └── manifest.json
└── dist
  ├── lib.js
  ├── lib.js.map
  └── manifest.json

文件說明:

  1. lib.js可以作為編譯好的靜態(tài)資源文件直接在頁面中通過src鏈接引入,與externals的資源引入方式一樣,生產(chǎn)與開發(fā)環(huán)境可以通過類似charles之類的代理轉(zhuǎn)發(fā)工具來做路由替換;
  2. manifest.json中保存了webpack中的預(yù)編譯信息,這樣等于提前拿到了依賴庫中的chunk信息,在實際開發(fā)過程中就無需要進行重復(fù)編譯;

2、dllPlugin的靜態(tài)資源引入

lib.js和manifest.json存在一一對應(yīng)的關(guān)系,所以我們在調(diào)用的過程也許遵循這個原則,如當(dāng)前處于開發(fā)階段,對應(yīng)我們可以引入common/debug文件夾下的lib.js和manifest.json,切換到生產(chǎn)環(huán)境的時候則需要引入common/dist下的資源進行對應(yīng)操作,這里考慮到手動切換和維護的成本,我們推薦使用add-asset-html-webpack-plugin進行依賴資源的注入,可得到如下結(jié)果:

<head>
<script src="/static/common/lib.js"></script>
</head>

在webpack.config.js文件中增加如下代碼:

const isDebug = (process.env.NODE_ENV === 'development');
const libPath = isDebug ? '../dll/lib/manifest.json' : 
'../dll/dist/lib/manifest.json';

// 將mainfest.json添加到webpack的構(gòu)建中

module.export = {
 plugins: [
    new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require(libPath),
   })
 ]
}

配置完成后我們能發(fā)現(xiàn)對應(yīng)的資源包已經(jīng)完成了純業(yè)務(wù)模塊的提取

多個工程之間如果需要使用共同的lib資源,也只需要引入對應(yīng)的lib.js和manifest.js即可,plugin配置中也支持多個webpack.DllReferencePlugin同時引入使用,如下:

module.export = {
 plugins: [
   new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require(libPath),
   }),
   new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require(ChartsPath),
   })
 ]
}

方案四、使用 Happypack 加速你的代碼構(gòu)建

以上介紹均為針對webpack中的chunk計算和編譯內(nèi)容的優(yōu)化與改進,對資源的實際體積改進上也較為明顯,那么除此之外,我們能否針對資源的編譯過程和速度優(yōu)化上做些嘗試呢?

眾所周知,webpack中為了方便各種資源和類型的加載,設(shè)計了以loader加載器的形式讀取資源,但是受限于node的編程模型影響,所有的loader雖然以async的形式來并發(fā)調(diào)用,但是還是運行在單個 node的進程以及在同一個事件循環(huán)中,這就直接導(dǎo)致了當(dāng)我們需要同時讀取多個loader文件資源時,比如babel-loader需要transform各種jsx,es6的資源文件。在這種同步計算同時需要大量耗費cpu運算的過程中,node的單進程模型就無優(yōu)勢了,那么happypack就針對解決此類問題而生。

開啟happypack的線程池

happypack的處理思路是將原有的webpack對loader的執(zhí)行過程從單一進程的形式擴展多進程模式,原本的流程保持不變,這樣可以在不修改原有配置的基礎(chǔ)上來完成對編譯過程的優(yōu)化,具體配置如下:

const HappyPack = require('happypack');
 const os = require('os')
 const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length}); // 啟動線程池});

module:{
  rules: [
   {
    test: /\.(js|jsx)$/,
    // use: ['babel-loader?cacheDirectory'],
    use: 'happypack/loader?id=jsx',
    exclude: /^node_modules$/
   }
  ]
 },
 plugins:[
  new HappyPack({
   id: 'jsx',
   cache: true,
   threadPool: HappyThreadPool,
   loaders: ['babel-loader']
  })
 ]

我們可以看到通過在loader中配置直接指向happypack提供的loader,對于文件實際匹配的處理 loader,則是通過配置在plugin屬性來傳遞說明,這里happypack提供的loader與plugin的銜接匹配,則是通過id=happybabel來完成。配置完成后,laoder的工作模式就轉(zhuǎn)變成了如下所示:

happypack在編譯過程中除了利用多進程的模式加速編譯,還同時開啟了cache計算,能充分利用緩存讀取構(gòu)建文件,對構(gòu)建的速度提升也是非常明顯的,經(jīng)過測試,最終的構(gòu)建速度提升如下:

優(yōu)化前:


優(yōu)化后:


關(guān)于happyoack的更多介紹可以查看:

happypack

方案五、增強 uglifyPlugin

uglifyJS憑借基于node開發(fā),壓縮比例高,使用方便等諸多優(yōu)點已經(jīng)成為了js壓縮工具中的首選,但是我們在webpack的構(gòu)建中觀察發(fā)現(xiàn),當(dāng)webpack build進度走到80%前后時,會發(fā)生很長一段時間的停滯,經(jīng)測試對比發(fā)現(xiàn)這一過程正是uglfiyJS在對我們的output中的bunlde部分進行壓縮耗時過長導(dǎo)致,針對這塊我們可以使用webpack-uglify-parallel來提升壓縮速度。

從插件源碼中可以看到,webpack-uglify-parallel的是實現(xiàn)原理是采用了多核并行壓縮的方式來提升我們的壓縮速度。

plugin.nextWorker().send({
  input: input,
  inputSourceMap: inputSourceMap,
  file: file,
  options: options
});

plugin._queue_len++;
        
if (!plugin._queue_len) {
  callback();
}        

if (this.workers.length < this.maxWorkers) {
  var worker = fork(__dirname + '/lib/worker');
  worker.on('message', this.onWorkerMessage.bind(this));
  worker.on('error', this.onWorkerError.bind(this));
  this.workers.push(worker);
}

this._next_worker++;
return this.workers[this._next_worker % this.maxWorkers];

使用配置也非常簡單,只需要將我們原來webpack中自帶的uglifyPlugin配置:

new webpack.optimize.UglifyJsPlugin({
  exclude:/\.min\.js$/
  mangle:true,
  compress: { warnings: false },
  output: { comments: false }
})

修改成如下代碼即可:

const os = require('os');
  const UglifyJsParallelPlugin = require('webpack-uglify-parallel');
  
  new UglifyJsParallelPlugin({
   workers: os.cpus().length,
   mangle: true,
   compressor: {
    warnings: false,
    drop_console: true,
    drop_debugger: true
    }
  })

目前webpack官方也維護了一個支持多核壓縮的UglifyJs插件:uglifyjs-webpack-plugin,使用方式類似,優(yōu)勢在于完全兼容webpack.optimize.UglifyJsPlugin中的配置,可以通過uglifyOptions寫入,因此也做為推薦使用,參考配置如下:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
 new UglifyJsPlugin({
  uglifyOptions: {
   ie8: false,
   ecma: 8,
   mangle: true,
   output: { comments: false },
   compress: { warnings: false }
  },
  sourceMap: false,
  cache: true,
  parallel: os.cpus().length * 2
 })

方案六、Tree-shaking & Scope Hoisting

wepback在2.X和3.X中從rolluo中借鑒了tree-shakingScope Hoisting,利用es6的module特性,利用AST對所有引用的模塊和方法做了靜態(tài)分析,從而能有效地剔除項目中的沒有引用到的方法,并將相關(guān)方法調(diào)用歸納到了獨立的webpack_module中,對打包構(gòu)建的體積優(yōu)化也較為明顯,但是前提是所有的模塊寫法必須使用ES6 Module進行實現(xiàn),具體配置參考如下:

 // .babelrc: 通過配置減少沒有引用到的方法
 {
  "presets": [
   ["env", {
    "targets": {
     "browsers": ["last 2 versions", "safari >= 7"]
    }
   }],
   // https://www.zhihu.com/question/41922432
   ["es2015", {"modules": false}] // tree-shaking
  ]
 }

 // webpack.config: Scope Hoisting
 {
  plugins:[
   // https://zhuanlan.zhihu.com/p/27980441
   new webpack.optimize.ModuleConcatenationPlugin()
  ]
 }

適用場景

在實際的開發(fā)過程中,可靈活地選擇適合自身業(yè)務(wù)場景的優(yōu)化手段。

優(yōu)化手段 開發(fā)環(huán)境 生產(chǎn)環(huán)境
CommonsChunk
externals  
DllPlugin
Happypack  
uglify-parallel  

工程演示demo

溫馨提醒

本文中的所有例子已經(jīng)重新優(yōu)化,支持最新的webpack3特性,并附帶有分享ppt地址,可以在線點擊查看

小結(jié)

性能優(yōu)化無小事,追求快沒有止境,在前端工程日益龐大復(fù)雜的今天,針對實際項目,持續(xù)改進構(gòu)建工具的性能,對項目開發(fā)效率的提升和工具深度理解都是極其有益的。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • js控制不同的時間段顯示不同的css樣式的實例代碼

    js控制不同的時間段顯示不同的css樣式的實例代碼

    這篇文章介紹了js控制不同的時間段顯示不同的css樣式的實例代碼,有需要的朋友可以參考一下
    2013-11-11
  • 原生javascript單例模式的應(yīng)用實例分析

    原生javascript單例模式的應(yīng)用實例分析

    這篇文章主要介紹了原生javascript單例模式的應(yīng)用,結(jié)合實例形式分析了JavaScript單例模式的基本功能、原理、應(yīng)用及操作注意事項,需要的朋友可以參考下
    2020-02-02
  • JavaScript實現(xiàn)簡單的Markdown語法解析器

    JavaScript實現(xiàn)簡單的Markdown語法解析器

    Markdown 是一種輕量級標(biāo)記語言, 它允許人們使用易讀易寫的純文本格式編寫文檔,然后轉(zhuǎn)換成有效的 XHTML(或者HTML)文檔。本文將利用JavaScript實現(xiàn)簡單的Markdown語法解析器,感興趣的可以了解一下
    2023-03-03
  • 九個超級好用的Javascript技巧

    九個超級好用的Javascript技巧

    在實際的開發(fā)工作過程中,積累了一些常見又超級好用的 Javascript 技巧和代碼片段,包括整理的其他大神的 JS 使用技巧,今天篩選了 9 個,以供大家參考
    2023-04-04
  • 用JS生成UUID的方法實例

    用JS生成UUID的方法實例

    下面小編就為大家?guī)硪黄肑S生成UUID的方法實例。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-03-03
  • JavaScript中你不知道的Object.entries用法

    JavaScript中你不知道的Object.entries用法

    大家應(yīng)該都知道,Object.entries()方法返回一個給定對象自身可枚舉屬性的鍵值對數(shù)組,其排列與使用 for...in 循環(huán)遍歷該對象時返回的順序一致,這篇文章主要給大家介紹了關(guān)于JavaScript中你不知道的Object.entries用法的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • js使用i18n實現(xiàn)頁面國際化的方法

    js使用i18n實現(xiàn)頁面國際化的方法

    本篇文章主要介紹了js使用i18n實現(xiàn)頁面國際化的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • JS實現(xiàn)燈泡開關(guān)特效

    JS實現(xiàn)燈泡開關(guān)特效

    這篇文章主要為大家詳細介紹了JS實現(xiàn)燈泡開關(guān)特效,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • 后端要求formdata傳參前端該怎么處理詳解

    后端要求formdata傳參前端該怎么處理詳解

    這篇文章主要介紹了前端如何使用FormData對象進行數(shù)據(jù)傳參,包括創(chuàng)建FormData對象、添加數(shù)據(jù)、發(fā)送請求等步驟,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-03-03
  • JavaScript實現(xiàn)封閉區(qū)域布爾運算的示例代碼

    JavaScript實現(xiàn)封閉區(qū)域布爾運算的示例代碼

    這篇文章主要介紹了JavaScript實現(xiàn)封閉區(qū)域布爾運算的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06

最新評論

体育| 杭州市| 美姑县| 得荣县| 米泉市| 五大连池市| 土默特左旗| 西华县| 灵台县| 道孚县| 留坝县| 陵川县| 鹿泉市| 芦山县| 招远市| 太原市| 英德市| 长春市| 广河县| 普格县| 江都市| 荃湾区| 谷城县| 巩义市| 庆元县| 新蔡县| 同仁县| 荆门市| 乌兰县| 凤阳县| 湟源县| 会昌县| 雅江县| 大同县| 华安县| 三原县| 永丰县| 汝城县| 青浦区| 河西区| 滨州市|