recherche
Maisoninterface Webjs tutorielRésumé de l'optimisation des performances frontales Js

Résumé de l'optimisation des performances frontales Js

Feb 28, 2018 pm 01:42 PM
javascript优化总结

La meilleure optimisation des ressources est de ne pas charger de ressources. La mise en cache est également la méthode d'optimisation la plus efficace. Pour être honnête, bien que la mise en cache côté client s'effectue du côté du navigateur, la mise en cache est principalement contrôlée par le serveur et n'a pas grand-chose à voir avec notre front-end. Mais encore faut-il comprendre.

La mise en cache inclut la mise en cache côté serveur et la mise en cache côté client. Cet article ne parle que de la mise en cache côté client. Le cache dit client est principalement du cache http. La mise en cache HTTP est principalement divisée en mise en cache forcée et mise en cache négociée.

Mise en cache forcée

  • Expire (http1.0)

Utilisez Expire dans http1.0 pour effectuer une mise en cache forcée. La valeur de Expires est le délai d'expiration des données renvoyées par le serveur. Lorsque le temps de requête lors d'une nouvelle demande est inférieur au temps renvoyé, les données mises en cache seront utilisées directement. Cependant, étant donné que l'heure du serveur et celle du client peuvent être différentes, cela entraînera également des erreurs d'accès au cache.

  • Cache-Control

Cache-Control a de nombreux attributs, et différents attributs ont des significations différentes.

  1. privé : le client peut mettre en cache

  2. public : le client et le serveur proxy peuvent mettre en cache

  3. max-age=t : Le contenu mis en cache expirera après t secondes

  4. no-cache : Nécessité d'utiliser un cache négocié pour vérifier les données mises en cache

  5. no-store : tout le contenu ne sera pas mis en cache.

Négocier le cache

La première fois que le navigateur demande des données, le serveur répondra au client avec l'ID du cache et les données, et le client les sauvegardera dans la cache. Lors d'une nouvelle demande, le client enverra l'identifiant présent dans le cache au serveur, et le serveur jugera en fonction de cet identifiant. S'il n'a pas expiré, un code d'état 304 sera renvoyé. Le navigateur pourra utiliser les données mises en cache directement après avoir reçu ce code d'état.

  • Dernière modification

Lorsque le serveur répond à la demande, il indiquera au navigateur l'heure de la dernière modification de la ressource

  • if-Modified-Since

Lorsque le navigateur demandera à nouveau le serveur, l'en-tête de la requête contiendra ce champ, suivi du Last-Modified (dernier heure de modification) obtenue dans le cache). Lorsque le serveur reçoit cet en-tête de requête et qu'il y a if-Modified-Since, il le compare avec l'heure de dernière modification de la ressource demandée. Si elle est supérieure à l'heure de dernière modification de la ressource demandée, il renvoie 304, et le navigateur. obtient la ressource du cache. Si elle est inférieure à l'heure de la dernière modification de la ressource demandée, 200 est renvoyé et la dernière ressource est renvoyée. Le navigateur obtient la dernière ressource du serveur et la met en cache.

  • Etag

Une chaîne d'identification unique générée par le serveur pour chaque ressource

  • Si - Aucun-Match

Lors d'une nouvelle demande au serveur, l'en-tête du message de demande du navigateur contiendra ce champ et la valeur suivante est l'identifiant obtenu dans le cache. Après avoir reçu le message, le serveur trouve If-None-Match et le compare avec l'identifiant unique de la ressource demandée. S'ils sont identiques, cela signifie que la ressource n'a pas été modifiée, renvoyez 304 et le navigateur obtient la ressource du cache. S'ils sont différents, cela signifie que la ressource a été modifiée, renvoyez 200 et renvoyez le. dernière ressource. Le navigateur obtient la dernière ressource du serveur et la met en cache.

Last-Modified et ETag peuvent être utilisés ensemble. Le serveur vérifiera d'abord l'ETag s'ils sont cohérents, il continuera à comparer Last-Modified et décidera enfin s'il doit renvoyer 304.

Si vous utilisez un outil de packaging frontal, vous pouvez ajouter un numéro de version ou une valeur de hachage au fichier lors du packaging, et vous pouvez également distinguer si la ressource a expiré.

Réduire les requêtes http

  • Utiliser CDN pour héberger des ressources statiques

  • Vous pouvez utiliser des outils d'empaquetage tels que gulp et webpack pour package js et css Attendez que les fichiers soient fusionnés et compressés

  • Les images sont chargées paresseusement et à la demande, et les images ne sont chargées que lors du défilement vers la zone visible de l'image

  • Petites images et images qui ne changeront pratiquement pas sont transmises en utilisant le codage base64. N'abusez pas de base64. Même les petites images généreront de très longues chaînes après l'encodage en base64. Si vous abusez de base64, cela sera contre-productif, car si une image est modifiée, l'image entière du sprite sera régénérée si elle est utilisée. sans discernement, cela sera contre-productif.

  • Réduire la taille des ressources de requête http

Utiliser Webpack, gulp et d'autres outils pour compresser les ressources

  • Activez la compression gzip sur le serveur (le taux de compression est très impressionnant, généralement supérieur à 30%)

  • Si vous utilisez des outils de packaging, l'optimisation du packaging doit être bien faite, ressources publiques , extraction de code tiers, Il n'y a pas besoin de bibliothèques packagées...

  • Optimisation du rendu

  • Ceux qui ont lu le mécanisme d'exécution js précédent doivent savoir que le L'URL est saisie depuis le navigateur vers la page apparaissant à l'écran, ce qui s'est passé (la poignée de main TCP, la résolution DNS, etc. ne sont pas à la portée des connaissances).

FPS 16 ms, moins de 10 ms est le meilleur, utilisez Google devtool pour vérifier la fréquence d'images

Si le FPS du navigateur atteint 60, il apparaîtra plus fluide. La fréquence de rafraîchissement de la plupart des moniteurs est de 60 Hz et le navigateur actualisera automatiquement les animations à cette fréquence.
Calculé sur la base d'un FPS égal à 60, le temps de trame moyen est de 1000 ms/60 = 16,7 ms, donc chaque temps de rendu ne peut pas dépasser 16 ms. S'il dépasse ce temps, une perte de trame et un décalage se produiront.

Vous pouvez vérifier le taux de rafraîchissement dans la chronologie des outils de développement du navigateur Chrome, et vous pouvez vérifier la consommation de temps de toutes les fréquences d'images et l'exécution d'une certaine image. Tutoriel d'utilisation de la timeline : https://segmentfault.com/a/11...

Afin de garantir des FPS normaux, une certaine optimisation des performances de rendu est encore nécessaire. Voici toutes les stratégies liées à l’optimisation du rendu.

  • Essayez d'utiliser CSS3 pour les animations

Comme nous le savons tous, les performances de CSS sont plus rapides que celles de JS, vous pouvez donc utiliser CSS et essayez de ne pas utiliser js Pour implémenter

  • évitez d'utiliser setTimeout ou setInterval, essayez d'utiliser requestAnimationFrame pour l'animation ou les opérations Dom à haute fréquence.

Étant donné que setTimeout et setInterval ne peuvent pas garantir le timing d'exécution de la fonction de rappel, elle est susceptible d'être exécutée à la fin de la trame, entraînant une perte de trame, mais requestAnimationFrame peut garantir que le La fonction de rappel sera exécutée au début de chaque image d'animation lors de l'exécution de
requestAnimationFrame Adresse MDN chinoise : https://developer.mozilla.org...

  • Calcul complexe. les opérations utilisent des Web Workers

Si vous avez besoin d'opérations de données complexes, telles que parcourir et additionner un tableau d'éléments, alors les Web Workers sont parfaits.

Les Web Workers peuvent autoriser l'exécution de scripts JavaScript dans des threads d'arrière-plan (similaires à la création d'un thread enfant), et le thread d'arrière-plan n'affectera pas la page du thread principal. Cependant, les threads créés à l'aide de Web Workers ne peuvent pas exploiter l'arborescence DOM.
Pour plus d'informations sur les Web Workers, vous pouvez consulter l'explication détaillée de MDN : https://developer.mozilla.org...

  • css est placé en tête et js est placé à la queue.

Ceux qui ont lu le mécanisme d'exécution de js précédent devraient connaître le processus de rendu des pages, je n'entrerai donc pas dans les détails. Placer le CSS en tête évitera le phénomène de re-mise en page de l'écran de démarrage après la génération de l'arborescence html js qui a généralement un plus grand impact sur la page et est généralement placé à la fin pour la dernière exécution.

  • Anti-rebond et limitation d'événements

Pour les événements déclenchés à haute fréquence (déplacement de la souris, défilement) et d'autres événements, s'il n'est pas contrôlé, il peut déclencher de nombreux événements dans un court laps de temps.

La fonction anti-shake signifie que lorsqu'il est déclenché fréquemment, le code ne sera exécuté qu'une seule fois s'il y a suffisamment de temps libre. Scénario : Dans la zone de saisie de l'e-mail lors de l'inscription, au fur et à mesure que l'utilisateur saisit, il est jugé en temps réel si le format de l'e-mail est correct. Lorsque le premier événement de saisie est déclenché, définissez le timing : effectuez la vérification après 800 ms. Si seulement 100 ms se sont écoulées et que le dernier minuteur n'a pas été exécuté, effacez le minuteur et resynchronisez-le à 800 ms. Jusqu'à la dernière entrée, il n'y a pas d'entrée adjacente, le timing de cette dernière entrée se termine et le code de contrôle est finalement exécuté.

const filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;  
$("#email").on("keyup",checkEmail());  
function checkEmail(){  
    let timer=null;  
    return function (){  
        clearTimeout(timer);  
        timer=setTimeout(function(){  
            console.log('执行检查');  
        },800);  
    }  
}

La limitation des fonctions signifie que la méthode js ne s'exécute qu'une seule fois au cours d'une certaine période de temps. Autrement dit, ce qui était initialement exécuté 100 fois par seconde devient 10 fois par seconde.
Scénario : le scénario réel de l'application de limitation de fonctions, dont la plupart seront utilisés lors de la surveillance des événements de défilement des éléments de la page.

var canRun = true;
document.getElementById("throttle").onscroll = function(){
    if(!canRun){
        // 判断是否已空闲,如果在执行中,则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函数节流");
        canRun = true;
    }, 300);
};
  • Opération Dom

Les développeurs front-end savent tous que l'opération Do prend beaucoup de temps (j'en ai personnellement testé 30* 30 parcours de table pour ajouter des styles). Essayez donc d'éviter les opérations Dom fréquentes. Si vous ne pouvez pas l'éviter, essayez d'optimiser les opérations DOm.

1.:缓存Dom查询,比如通过getElementByTagName('p')获取Dom集,而不是逐个获取。

2: 合并Dom操作,使用createDocumentFragment()
    var frag = document.createDocumentFragment()
    for (i<pre class="brush:php;toolbar:false"> 3: 使用React、Vue等框架的虚拟dom(原理目前还不明白),可以更快的实现dom操作。
  • Essayez d'éviter de repeindre et de refusionner

Si vous utilisez js pour modifier des éléments La couleur ou l'arrière-plan La couleur déclenchera le redessin, et le coût du redessin est encore relativement élevé, car le navigateur vérifiera tous les nœuds d'un élément DOM après que l'effet visuel des changements d'élément DOM.

Si la taille et la position de l'élément sont modifiées, une redistribution se produira. La redistribution est plus coûteuse. Elle sera déclenchée après le changement de la position d'un certain élément DOM, et elle recalculera la position de tous les éléments et. leur placement sur la page. La zone occupée entraînera le rendu d'une certaine partie de la page, voire de la page entière.

  • Accélération matérielle CSS3

Lors du rendu du navigateur, il sera divisé en deux couches : une couche normale et une couche composite.

Le flux de documents ordinaire peut être compris comme une couche composite. Bien que la mise en page absolue et fixe puisse être séparée du flux de documents ordinaire, elle appartient toujours à la couche ordinaire et l'accélération matérielle ne sera pas activée. La repeinture et la refusion mentionnées ci-dessus font référence au redessin et à la refusion sur des calques ordinaires.

Les couches composées permettront l’accélération matérielle. Il ne se trouve pas dans le même calque que le calque ordinaire, donc le calque composite n'affectera pas le calque ordinaire. Si un élément est promu au calque composite, puis que l'élément est exploité, cela n'entraînera pas le redessin du calque ordinaire. et redistribué. Cela améliore les performances de rendu.

Comment démarrer l'accélération matérielle :

1. Utilisez Translate3d et TranslateZ

.
webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);

webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
-o-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);

2.使用opacity
需要动画执行的过程中才会创建合成层,动画没有开始或结束后元素还会回到之前的状态

3.使用will-chang属性
这个属性比较不常用,一般配合opacity与translate使用

针对webkit浏览器,启用硬件加速有些时候可能会导致浏览器频繁闪烁或抖动,可以使用下面方法消除:

-webkit-backface-visibility:hidden;
-webkit-perspective:1000;
如果使用硬件加速,请使用z-index配合使用, 因为如果这个元素添加了硬件加速,并且index层级比较低, 那么在这个元素的后面其它元素(层级比这个元素高的,或者相同的,并且releative或absolute属性相同的), 会默认变为复合层渲染,如果处理不当会极大的影响性能
  • 避免强制同步布局和布局抖动

浏览器渲染过程为:js/css(javascript) > 计算样式(style) > 布局(layout) > 绘制(paint) > 渲染合并图层(Composite)

JavaScript:JavaScript实现动画效果,DOM元素操作等。
Style(计算样式):确定每个DOM元素应该应用什么CSS规则。
Layout(布局):计算每个DOM元素在最终屏幕上显示的大小和位置。
Paint(绘制):在多个层上绘制DOM元素的的文字、颜色、图像、边框和阴影等。
Composite(渲染层合并):按照合理的顺序合并图层然后显示到屏幕上。

在js中如果读取style属性的某些值就会让浏览器强行进行一次布局、计算,然后再返回值,比如:

offsetTop, offsetLeft, offsetWidth, offsetHeight

scrollTop/Left/Width/Height

clientTop/Left/Width/Height

width,height

请求了getComputedStyle(), 或者 IE的 currentStyle

所以,如果强制浏览器在执行JavaScript脚本之前先执行布局过程,这就是所谓的强制同步布局。
比如下面代码:

requestAnimationFrame(logBoxHeight);

// 先写后读,触发强制布局
function logBoxHeight() {
    // 更新box样式
    box.classList.add('super-big');

    // 为了返回box的offersetHeight值
    // 浏览器必须先应用属性修改,接着执行布局过程
    console.log(box.offsetHeight);
}

// 先读后写,避免强制布局
function logBoxHeight() {
    // 获取box.offsetHeight
    console.log(box.offsetHeight);

    // 更新box样式
    box.classList.add('super-big');
}

在JavaScript脚本运行的时候,它能获取到的元素样式属性值都是上一帧画面的,都是旧的值。因此,如果你在当前帧获取属性之前又对元素节点有改动,那就会导致浏览器必须先应用属性修改,结果执行布局过程,最后再执行JavaScript逻辑。

如果连续多次强制同步布局,就会导致布局抖动
比如下面代码:

function resizeAllParagraphsToMatchBlockWidth() {
  for (var i = 0; i <p>我们知道浏览器是一帧一帧的刷新页面的,对于每一帧,上一帧的布局信息都是已知的。<br>强制布局就是使用js强制浏览器提前布局,比如下面代码:</p><pre class="brush:php;toolbar:false">// bed  每次循环都要去获取left ,就会发生一次回流
function logBoxHeight() {
  box.style.left += 10
  console.log(box.style.left)
}

// goog 
var width = box.offsetWidth;

function resizeAllParagraphsToMatchBlockWidth() {
  for (var i = 0; i 
  • DOMContentLoaded与Load

DOMContentLoaded 事件触发时,仅当DOM加载完成才触发DOMContentLoaded,此时样式表,图片,外部引入资源都还没加载。而load是等所有的资源加载完毕才会触发。

1. 解析HTML结构。
2. 加载外部脚本和样式表文件。
3. 解析并执行脚本代码。
4. DOM树构建完成。//DOMContentLoaded
5. 加载图片等外部文件。
页面加载完毕。//load
  • 视觉优化

等待加载时间可以合理使用loading gif动图一定程度上消除用户等待时间的烦躁感

代码性能

代码对性能的影响可大可小,但是养成一个良好的写代码习惯和高质量的代码,会潜移默化的提高性能,同时也能提高自己的水平。废话不多说,直接看我总结的部分要点(因为这一部分知识点太多,需要大家写代码的时候多多总结)。

  • 避免全局查找

访问局部变量会比访问全局变量快,因为js查找变量的时候现在局部作用局查找,找不到在逐级向上找。

// bad
function f () {
    for (...){
        console.log(window.location.href)
    }
}

//good
function f () {
    var href = window.location.href
    for (...){
        console.log(href)
    }
}
  • 循环技巧

// bed 
for(var i = 0; i 
  • 不要使用for in 遍历数组

for in是最慢的,其他的都差不多,其中直接使用for循环是最快的。for in只是适合用来遍历对象。

  • 使用+''代替String()吧变量转化为字符串

var a = 12
//bad
a = String(a)

// good
var a = 12
a = a + ''

这个还有很多类似的,比如使用*1代替parseInt()等都是利用js的弱类型,其实这样对性能提升不是很大,网上有人测试过,进行十几万次变量转换,才快了零点几秒。

  • 删除dom

删除dom元素要删除注册在该节点上的事件,否则就会产生无法回收的内存,在选择removeChild和innerHTML=''二者之间尽量选择后者,据说removeChild有时候无法有效的释放节点(具体原因不明)

  • 使用事件代理处理事件

任何可以冒泡的事件都可以在节点的祖先节点上处理,这样对于子节点需要绑定相同事件的情况就不用分别给每个子节点添加事件监听,而是都提升到祖先节点处理。

  • 通过js生成的dom对象必须append到页面中

在IE下,js创建的额dom如果没有添加到页面,这部分内存是不会被回收的

  • 避免与null比较

可以使用下面方法替换与null比较
1.如果该值为引用类型,则使用instanceof检查其构造函数
2.如果该值为基本类型,使用typeof检查类型

  • 尽量使用三目运算符代替if else

if(a>b){num = a}
else{num = b}

// 可以替换为
num = a > b ? a : b
  • 当判断条件大于3中情况时,使用switch代替if

因为switch的执行速度比if要快,也别是在IE下,速度大约是if的两倍。

相关推荐:

CSS解读前端性能优化的具体分析

在HTML5中如何提高网站前端性能的示例代码分析

web前端性能优化方法


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Comprendre le moteur JavaScript: détails de l'implémentationComprendre le moteur JavaScript: détails de l'implémentationApr 17, 2025 am 12:05 AM

Comprendre le fonctionnement du moteur JavaScript en interne est important pour les développeurs car il aide à écrire du code plus efficace et à comprendre les goulots d'étranglement des performances et les stratégies d'optimisation. 1) Le flux de travail du moteur comprend trois étapes: analyse, compilation et exécution; 2) Pendant le processus d'exécution, le moteur effectuera une optimisation dynamique, comme le cache en ligne et les classes cachées; 3) Les meilleures pratiques comprennent l'évitement des variables globales, l'optimisation des boucles, l'utilisation de const et de locations et d'éviter une utilisation excessive des fermetures.

Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisationPython vs JavaScript: la courbe d'apprentissage et la facilité d'utilisationApr 16, 2025 am 12:12 AM

Python convient plus aux débutants, avec une courbe d'apprentissage en douceur et une syntaxe concise; JavaScript convient au développement frontal, avec une courbe d'apprentissage abrupte et une syntaxe flexible. 1. La syntaxe Python est intuitive et adaptée à la science des données et au développement back-end. 2. JavaScript est flexible et largement utilisé dans la programmation frontale et côté serveur.

Python vs JavaScript: communauté, bibliothèques et ressourcesPython vs JavaScript: communauté, bibliothèques et ressourcesApr 15, 2025 am 12:16 AM

Python et JavaScript ont leurs propres avantages et inconvénients en termes de communauté, de bibliothèques et de ressources. 1) La communauté Python est amicale et adaptée aux débutants, mais les ressources de développement frontal ne sont pas aussi riches que JavaScript. 2) Python est puissant dans les bibliothèques de science des données et d'apprentissage automatique, tandis que JavaScript est meilleur dans les bibliothèques et les cadres de développement frontaux. 3) Les deux ont des ressources d'apprentissage riches, mais Python convient pour commencer par des documents officiels, tandis que JavaScript est meilleur avec MDNWEBDOCS. Le choix doit être basé sur les besoins du projet et les intérêts personnels.

De C / C à JavaScript: comment tout cela fonctionneDe C / C à JavaScript: comment tout cela fonctionneApr 14, 2025 am 12:05 AM

Le passage de C / C à JavaScript nécessite de s'adapter à la frappe dynamique, à la collecte des ordures et à la programmation asynchrone. 1) C / C est un langage dactylographié statiquement qui nécessite une gestion manuelle de la mémoire, tandis que JavaScript est dynamiquement typé et que la collecte des déchets est automatiquement traitée. 2) C / C doit être compilé en code machine, tandis que JavaScript est une langue interprétée. 3) JavaScript introduit des concepts tels que les fermetures, les chaînes de prototypes et la promesse, ce qui améliore la flexibilité et les capacités de programmation asynchrones.

Moteurs JavaScript: comparaison des implémentationsMoteurs JavaScript: comparaison des implémentationsApr 13, 2025 am 12:05 AM

Différents moteurs JavaScript ont des effets différents lors de l'analyse et de l'exécution du code JavaScript, car les principes d'implémentation et les stratégies d'optimisation de chaque moteur diffèrent. 1. Analyse lexicale: convertir le code source en unité lexicale. 2. Analyse de la grammaire: générer un arbre de syntaxe abstrait. 3. Optimisation et compilation: générer du code machine via le compilateur JIT. 4. Exécuter: Exécutez le code machine. Le moteur V8 optimise grâce à une compilation instantanée et à une classe cachée, SpiderMonkey utilise un système d'inférence de type, résultant en différentes performances de performances sur le même code.

Au-delà du navigateur: Javascript dans le monde réelAu-delà du navigateur: Javascript dans le monde réelApr 12, 2025 am 12:06 AM

Les applications de JavaScript dans le monde réel incluent la programmation côté serveur, le développement des applications mobiles et le contrôle de l'Internet des objets: 1. La programmation côté serveur est réalisée via Node.js, adaptée au traitement de demande élevé simultané. 2. Le développement d'applications mobiles est effectué par le reactnatif et prend en charge le déploiement multiplateforme. 3. Utilisé pour le contrôle des périphériques IoT via la bibliothèque Johnny-Five, adapté à l'interaction matérielle.

Construire une application SaaS multi-locataire avec next.js (intégration backend)Construire une application SaaS multi-locataire avec next.js (intégration backend)Apr 11, 2025 am 08:23 AM

J'ai construit une application SAAS multi-locataire fonctionnelle (une application EdTech) avec votre outil technologique quotidien et vous pouvez faire de même. Premièrement, qu'est-ce qu'une application SaaS multi-locataire? Les applications saas multi-locataires vous permettent de servir plusieurs clients à partir d'un chant

Comment construire une application SaaS multi-locataire avec Next.js (Frontend Integration)Comment construire une application SaaS multi-locataire avec Next.js (Frontend Integration)Apr 11, 2025 am 08:22 AM

Cet article démontre l'intégration frontale avec un backend sécurisé par permis, construisant une application fonctionnelle EdTech SaaS en utilisant Next.js. Le frontend récupère les autorisations des utilisateurs pour contrôler la visibilité de l'interface utilisateur et garantit que les demandes d'API adhèrent à la base de rôles

See all articles

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Version crackée d'EditPlus en chinois

Version crackée d'EditPlus en chinois

Petite taille, coloration syntaxique, ne prend pas en charge la fonction d'invite de code

Version Mac de WebStorm

Version Mac de WebStorm

Outils de développement JavaScript utiles

Navigateur d'examen sécurisé

Navigateur d'examen sécurisé

Safe Exam Browser est un environnement de navigation sécurisé permettant de passer des examens en ligne en toute sécurité. Ce logiciel transforme n'importe quel ordinateur en poste de travail sécurisé. Il contrôle l'accès à n'importe quel utilitaire et empêche les étudiants d'utiliser des ressources non autorisées.

SublimeText3 version anglaise

SublimeText3 version anglaise

Recommandé : version Win, prend en charge les invites de code !

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP