前端入门到入土?(五)

简介: 前端入门到入土?

前言

hello world欢迎来到前端的新世界


😜当前文章系列专栏:前端面试

🐱‍👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家指出)🌹

💖感谢大家支持!您的观看就是作者创作的动力


webpack 层面如何做性能优化

优化前的准备工作


  • 准备基于时间的分析工具:我们需要一类插件,来帮助我们统计项目构建过程中在编译阶段的耗时情况。speed-measure-webpack-plugin 分析插件加载的时间
  • 使用 webpack-bundle-analyzer 分析产物内容


代码优化


无用代码消除,是许多编程语言都具有的优化手段,这个过程称为 DCE (dead code elimination),即 删除不可能执行的代码;


例如我们的 UglifyJs,它就会帮我们在生产环境中删除不可能被执行的代码,例如:


var fn = function() {
  return 1;
  // 下面代码便属于 不可能执行的代码;
  // 通过 UglifyJs (Webpack4+ 已内置) 便会进行 DCE;
  var a = 1;
  return a;
}


摇树优化 (Tree-shaking),这是一种形象比喻。我们把打包后的代码比喻成一棵树,这里其实表示的就是,通过工具 “摇” 我们打包后的 js 代码,将没有使用到的无用代码 “摇” 下来 (删除)。即 消除那些被 引用了但未被使用 的模块代码。


  • 原理: 由于是在编译时优化,因此最基本的前提就是语法的静态分析,ES6的模块机制 提供了这种可能性。不需要运行时,便可进行代码字面上的静态分析,确定相应的依赖关系。
  • 问题: 具有 副作用 的函数无法被 tree-shaking
  • 在引用一些第三方库,需要去观察其引入的代码量是不是符合预期;
  • 尽量写纯函数,减少函数的副作用;
  • 可使用 webpack-deep-scope-plugin,可以进行作用域分析,减少此类情况的发生,但仍需要注意;


code-spliting: 代码分割技术,将代码分割成多份进行 懒加载 或 异步加载,避免打包成一份后导致体积过大,影响页面的首屏加载;


  • Webpack 中使用 SplitChunksPlugin 进行拆分;
  • 按 页面 拆分: 不同页面打包成不同的文件;
  • 按 功能 拆分:
  • 将类似于播放器,计算库等大模块进行拆分后再懒加载引入;
  • 提取复用的业务代码,减少冗余代码;
  • 按 文件修改频率 拆分: 将第三方库等不常修改的代码单独打包,而且不改变其文件 hash 值,能最大化运用浏览器的缓存;


scope hoisting: 作用域提升,将分散的模块划分到同一个作用域中,避免了代码的重复引入,有效减少打包后的代码体积和运行时的内存损耗;

编译性能优化:


  • 升级至 最新 版本的 webpack,能有效提升编译性能;
  • 使用 dev-server / 模块热替换 (HMR) 提升开发体验;
  • 监听文件变动 忽略 node_modules 目录能有效提高监听时的编译效率;
  • 缩小编译范围
  • modules: 指定模块路径,减少递归搜索;
  • mainFields: 指定入口文件描述字段,减少搜索;
  • noParse: 避免对非模块化文件的加载;
  • includes/exclude: 指定搜索范围/排除不必要的搜索范围;
  • alias: 缓存目录,避免重复寻址;
  • babel-loader
  • 忽略node_moudles,避免编译第三方库中已经被编译过的代码
  • 使用cacheDirectory,可以缓存编译结果,避免多次重复编译
  • 多进程并发
  • webpack-parallel-uglify-plugin: 可多进程并发压缩 js 文件,提高压缩速度;
  • HappyPack: 多进程并发文件的 Loader 解析;
  • 第三方库模块缓存:
  • DLLPlugin 和 DLLReferencePlugin 可以提前进行打包并缓存,避免每次都重新编译;
  • 使用分析
  • Webpack Analyse / webpack-bundle-analyzer 对打包后的文件进行分析,寻找可优化的地方
  • 配置profile:true,对各个编译阶段耗时进行监控,寻找耗时最多的地方
  • source-map:
  • 开发: cheap-module-eval-source-map
  • 生产: hidden-source-map;


优化webpack打包速度


  • 减少文件搜索范围
  • 比如通过别名
  • loader 的 test,include & exclude
  • Webpack4 默认压缩并行
  • Happypack 并发调用
  • babel 也可以缓存编译
  • Resolve 在构建时指定查找模块文件的规则
  • 使用DllPlugin,不用每次都重新构建
  • externals 和 DllPlugin 解决的是同一类问题:将依赖的框架等模块从构建过程中移除。它们的区别在于
  • 在 Webpack 的配置方面,externals 更简单,而 DllPlugin 需要独立的配置文件。
  • DllPlugin 包含了依赖包的独立构建流程,而 externals 配置中不包含依赖框架的生成方式,通常使用已传入 CDN 的依赖包
  • externals 配置的依赖包需要单独指定依赖模块的加载方式:全局对象、CommonJS、AMD 等
  • 在引用依赖包的子模块时,DllPlugin 无须更改,而 externals 则会将子模块打入项目包中


优化打包体积


  • 提取第三方库或通过引用外部文件的方式引入第三方库
  • 代码压缩插件UglifyJsPlugin
  • 服务器启用gzip压缩
  • 按需加载资源文件 require.ensure
  • 优化devtool中的source-map
  • 剥离css文件,单独打包
  • 去除不必要插件,通常就是开发环境与生产环境用同一套配置文件导致
  • Tree Shaking 在构建打包过程中,移除那些引入但未被使用的无效代码
  • 开启 scope hosting
  • 体积更小
  • 创建函数作用域更小
  • 代码可读性更好

默认打包





介绍一下 Tree Shaking

对tree-shaking的了解

作用:

它表示在打包的时候会去除一些无用的代码


原理:


  • ES6的模块引入是静态分析的,所以在编译时能正确判断到底加载了哪些模块
  • 分析程序流,判断哪些变量未被使用、引用,进而删除此代码


特点


  • 在生产模式下它是默认开启的,但是由于经过babel编译全部模块被封装成IIFE,它存在副作用无法被tree-shaking掉
  • 可以在package.json中配置sideEffects来指定哪些文件是有副作用的。它有两种值,一个是布尔类型,如果是false则表示所有文件都没有副作用;如果是一个数组的话,数组里的文件路径表示改文件有副作用
  • rollup和webpack中对tree-shaking的层度不同,例如对babel转译后的class,如果babel的转译是宽松模式下的话(也就是loose为true),webpack依旧会认为它有副作用不会tree-shaking掉,而rollup会。这是因为rollup有程序流分析的功能,可以更好的判断代码是否真正会产生副作用。


依赖于import/export


通过导入所有的包后再进行条件获取。如下:


import foo from "foo";
import bar from "bar";
if(condition) {
    // foo.xxxx
} else {
    // bar.xxx
}


ES6的import语法完美可以使用tree shaking,因为可以在代码不运行的情况下就能分析出不需要的代码


CommonJS的动态特性模块意味着tree shaking不适用。因为它是不可能确定哪些模块实际运行之前是需要的或者是不需要的。在ES6中,进入了完全静态的导入语法:import。这也意味着下面的导入是不可行的:


// 不可行,ES6 的import是完全静态的
if(condition) {
    myDynamicModule = require("foo");
} else {
    myDynamicModule = require("bar");
}



Webpack Proxy工作原理?为什么能解决跨域

1.是什么

webpack proxy,即webpack提供的代理服务


基本行为就是接收客户端发送的请求后转发给其他服务器


其目的是为了便于开发者在开发模式下解决跨域问题(浏览器安全策略限制)


想要实现代理首先需要一个中间服务器,webpack中提供服务器的工具为webpack-dev-server


2.webpack-dev-server


webpack-dev-serverwebpack 官方推出的一款开发工具,将自动编译和自动刷新浏览器等一系列对开发友好的功能全部集成在了一起


目的是为了提高开发者日常的开发效率,「只适用在开发阶段」


关于配置方面,在webpack配置对象属性中通过devServer属性提供,如下:


// ./webpack.config.js
const path = require('path')
module.exports = {
    // ...
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 9000,
        proxy: {
            '/api': {
                target: 'https://api.github.com'
            }
        }
        // ...
    }
}


devServetr里面proxy则是关于代理的配置,该属性为对象的形式,对象中每一个属性就是一个代理的规则匹配


属性的名称是需要被代理的请求路径前缀,一般为了辨别都会设置前缀为/api,值为对应的代理匹配规则,对应如下:


  • target:表示的是代理到的目标地址
  • pathRewrite:默认情况下,我们的 /api-hy 也会被写入到URL中,如果希望删除,可以使用pathRewrite
  • secure:默认情况下不接收转发到https的服务器上,如果希望支持,可以设置为false
  • changeOrigin:它表示是否更新代理后请求的 headers 中host地址


3.工作原理


proxy工作原理实质上是利用http-proxy-middleware 这个http代理中间件,实现请求转发给其他服务器


举个例子:


在开发阶段,本地地址为http://localhost:3000,该浏览器发送一个前缀带有/api标识的请求到服务端获取数据,但响应这个请求的服务器只是将请求转发到另一台服务器中


const express = require('express');
const proxy = require('http-proxy-middleware');
const app = express();
app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}));
app.listen(3000);
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar


4. 跨域


在开发阶段, webpack-dev-server 会启动一个本地开发服务器,所以我们的应用在开发阶段是独立运行在 localhost的一个端口上,而后端服务又是运行在另外一个地址上


所以在开发阶段中,由于浏览器同源策略的原因,当本地访问后端就会出现跨域请求的问题


通过设置webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者


当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将

数据返回给代理服务器,最终再由代理服务器将数据响应给本地



在代理服务器传递数据给本地浏览器的过程中,两者同源,并不存在跨域行为,这时候浏览器就能正常接收数据


注意:「服务器与服务器之间请求数据并不会存在跨域行为,跨域行为是浏览器安全策略限制」


后言

创作不易,要是本文章对广大读者有那么一点点帮助 不妨三连支持一下,您的鼓励就是博主创作的动力


目录
相关文章
|
2月前
|
前端开发 机器人 API
前端大模型入门(一):用 js+langchain 构建基于 LLM 的应用
本文介绍了大语言模型(LLM)的HTTP API流式调用机制及其在前端的实现方法。通过流式调用,服务器可以逐步发送生成的文本内容,前端则实时处理并展示这些数据块,从而提升用户体验和实时性。文章详细讲解了如何使用`fetch`发起流式请求、处理响应流数据、逐步更新界面、处理中断和错误,以及优化用户交互。流式调用特别适用于聊天机器人、搜索建议等应用场景,能够显著减少用户的等待时间,增强交互性。
627 2
|
3月前
|
前端开发
【前端web入门第四天】02 CSS三大特性+背景图
本文详细介绍了CSS的三大特性:继承性、层叠性和优先级,并深入讲解了背景图的相关属性,包括背景属性、背景图的平铺方式、位置设定、缩放、固定以及复合属性。其中,继承性指子元素自动继承父元素的文字控制属性;层叠性指相同属性后定义覆盖前定义,不同属性可叠加;优先级涉及选择器权重,包括行内样式、ID选择器等。背景图部分则通过具体示例展示了如何设置背景图像的位置、大小及固定方式等。
267 91
|
1月前
|
编解码 前端开发 JavaScript
从入门到精通:揭秘前端开发中那些不为人知的优化秘籍!
前端开发是充满无限可能的领域,从初学者到资深专家,每个人都追求更快、更稳定、更用户体验友好的网页。本文介绍了四大优化秘籍:1. HTML的精简与语义化;2. CSS的优雅与高效;3. JavaScript的精简与异步加载;4. 图片与资源的优化。通过这些方法,可以显著提升网页性能和用户体验。
24 3
|
1月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
133 1
|
1月前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
45 0
|
3月前
|
JavaScript 前端开发 小程序
一小时入门Vue.js前端开发
本文是作者关于Vue.js前端开发的快速入门教程,包括结果展示、参考链接、注意事项以及常见问题的解决方法。文章提供了Vue.js的基础使用介绍,如何安装和使用cnpm,以及如何解决命令行中遇到的一些常见问题。
一小时入门Vue.js前端开发
|
2月前
|
自然语言处理 资源调度 前端开发
前端大模型入门(四):不同文本分割器对比和效果展示-教你如何根据场景选择合适的长文本分割方式
本文详细介绍了五种Langchain文本分割器:`CharacterTextSplitter`、`RecursiveCharacterTextSplitter`、`TokenTextSplitter`、`MarkdownTextSplitter` 和 `LatexTextSplitter`,从原理、优缺点及适用场景等方面进行了对比分析,旨在帮助开发者选择最适合当前需求的文本分割工具,提高大模型应用的处理效率和效果。
226 1
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
前端大模型入门(三):编码(Tokenizer)和嵌入(Embedding)解析 - llm的输入
本文介绍了大规模语言模型(LLM)中的两个核心概念:Tokenizer和Embedding。Tokenizer将文本转换为模型可处理的数字ID,而Embedding则将这些ID转化为能捕捉语义关系的稠密向量。文章通过具体示例和代码展示了两者的实现方法,帮助读者理解其基本原理和应用场景。
559 1
|
2月前
|
人工智能 前端开发 JavaScript
前端大模型入门(二):掌握langchain的核心Runnable接口
Langchain.js 是 Langchain 框架的 JavaScript 版本,专为前端和后端 JavaScript 环境设计。最新 v0.3 版本引入了强大的 Runnable 接口,支持灵活的执行方式和异步操作,方便与不同模型和逻辑集成。本文将详细介绍 Runnable 接口,并通过实现自定义 Runnable 来帮助前端人员快速上手。
|
2月前
|
存储 JavaScript 前端开发
前端开发:Vue.js入门与实战
【10月更文挑战第9天】前端开发:Vue.js入门与实战

热门文章

最新文章