先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip204888 (备注网络安全)
正文
- 🤾♀️序言
- 🏓一、Tree Shaking
- 🏸二、Development和Prodiction模式的区分打包
- ⚽三、Webpack和Code Splitting、SplitChunksPlugin
- 🏐四、打包分析,Preloading,Prefetching
- 🏏五、CSS文件的代码分割
- 🏑六、webpack与浏览器缓存
- ⚾七、Shimming的作用
- 🎖️八、结束语
- 🐣彩蛋 One More Thing
🤾♀️序言
上一篇文章中我们讲到了 webpack
的一些基础特性,但是呢,单单会基础特性还是远远不够的。因此,在今天的文章中,将给大家带来 webpack
的高级特性,包括但不限于 dev
环境和 prod
环境的区分打包,以及使用 webpack
对项目进行代码分割等等技巧。
废话不多说,下面开始进入今天的学习吧~🎳
🏓一、Tree Shaking
1. 引例阐述
假设现在我们有一个需求,写一段程序来对两个数做加法和减法。现在,我们来实现这个功能。具体代码如下:
export const add = (a, b) => {
console.log(a + b);
}
export const minus = (a, b) => {
console.log(a - b);
}
接下来,我们在入口文件引入它。具体代码如下:
import { add } from './math.js';
add(1, 2);
在这种状态下,我们用 npx webpack
命令来对项目进行打包。查看打包后的文件代码:
/\*\*\*/ "./src/math.js":
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*!\*\
!\*\*\* ./src/math.js \*\*\*!
\\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*! exports provided: add, minus \*/
/\*\*\*/ (function(module, \_\_webpack\_exports\_\_, \_\_webpack\_require\_\_) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/\* harmony export (binding) \*/ __webpack_require__.d(__webpack_exports__, "add", function() { return add; });
/\* harmony export (binding) \*/ __webpack_require__.d(__webpack_exports__, "minus", function() { return minus; });
const add = (a, b) => {
console.log(a + b);
};
const minus = (a, b) => {
console.log(a - b);
};
/\*\*\*/ })
我们可以发现,在入口文件我们只引入了加法的操作,因为我们当下只想用到加法功能,而暂时还不需要用减法。但是呢,打包后的文件,把减法部分的内容,也一起,给打包进去了。这无形之中,多多少少给我们添加了不少麻烦。
因此呢,我们就需要引入 webpack
中的 Tree Shaking
,来解决这个问题。
2. Tree Shaking配置
首先我们需要在 webpack.common.js
里面进行配置。如果是在 Development
的模式下,那么默认是不拥有 Tree Shaking
的。因此需要进行以下配置,具体代码如下:
//node的核心模块
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode:'development',
optimization: {
usedExports: true
}
}
在开发环境下,我们需要加上 optimization
模块来对项目开启 Tree Shaking
。
接下来,我们继续对 package.json
进行配置。在这个文件下,我们需要添加以下代码:
{
"sideEffects": false
}
sideEffects:false
指的是什么意思呢?当设置为 false
时,表明对所有的 ES Module
开启 Tree Shaking
操作。
值得注意的是, Tree Shakig
只支持 ES Module
这种类型的引入,并不支持 commonJS
等类型的引入。这是因为, ES Module
的底层实现是静态的,而 commonJS
的实现则是动态的。
还有另外一种情况就是,如果你想要使得某些模块不开启 Tree Shaking
,那么可以将 sideEffects
进行以下配置。具体代码如下:
{
"sideEffects": [
"\*.css",
"@babel/poly-fill"
]
}
以上代码的意思为,对所有的 css
文件以及 @babel/poly-fill
不开启 Tree-shaking
功能。
接下来我们来看一下配置完成之后,在开发环境下的效果。具体代码如下:
/\*\*\*/ "./src/math.js":
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*!\*\
!\*\*\* ./src/math.js \*\*\*!
\\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*! exports provided: add, minus \*/
/\*! exports used: add \*/
/\*\*\*/ (function(module, \_\_webpack\_exports\_\_, \_\_webpack\_require\_\_) {
"use strict";
/\* harmony export (binding) \*/ __webpack_require__.d(__webpack_exports__, "a", function() { return add; });
/\* unused harmony export minus \*/
const add = (a, b) => {
console.log(a + b);
};
const minus = (a, b) => {
console.log(a - b);
};
/\*\*\*/ })
/\*\*\*\*\*\*/ });
//# sourceMappingURL=main.js.map
大家可以看到,如果是在开发模式下,减法功能依然是存在的,只是多个一句 /*! exports used: add */
来表明只使用 add
这个功能。
这是为什么呢?因为在开发模式下, webpack
怕这个地方如果引入了其他模块,那么删除就很容易导致报错,所以它没有进行删除。
但如果 mode
是在生产环境下时, Tree Shaking
的作用就比较明显了。我们修改完 mode
后来看下打包后的结果。具体代码如下:
function (e, n, r) { "use strict"; r.r(n); var t, o; t = 1, o = 2, console.log(t + o) }
生产环境下打包后只有一行,小编摘取了最终要的部分出来。
大家可以看到,当处于生产环境下时,打包后的结果只显示了加法功能。而我们没有使用到减法,所以这个时候就不会连带着打包出来了。
顺带着这个话题,接下来我们就来讲一下, webpack
在 development
和 Production
模式下的区分打包。
🏸二、Development和Prodiction模式的区分打包
1. 项目打包结构
通常情况下,我们的项目会有三个 webpack
的配置文件。一个是 webpack.common.js
,一个是 webpack.dev.js
,另外一个是webpack.prod.js
。第一个文件用来放开发环境和生产环境下共同的配置,第二个文件用来放开发环境下的配置,第三个文件用来放生产环境下的配置。
接下来我们来了解下,这三个配置文件的代码。
2. 共有配置webpack.common.js
如果我们不编写 common
文件的话,那么 dev
和 prod
这两个文件的代码重合度就会比较高,所以我们把相同的部分抽离出来。具体代码如下:
//node核心模块
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
// 放置入口文件,明确怎么打包
entry:{
main: './src/index.js'
},
module:{
rules:[{
test: /\.m?js$/,
//exclude,顾名思义即排除在外。如果js文件在node\_modules文件夹下面,那么我们就排除在外
// 因为node\_module一般都是来自于第三方库,它已经自动的处理好此部分工作,所以我们没必要再去做重复操作
exclude: /node\_modules/,
use: {
loader: "babel-loader",
}
},{
test:/\.(jpg|png|gif)$/,
use:{
loader:'file-loader',
options: {
//placeholder 占位符
name: '[name]\_[hash].[ext]',
outputPath: 'images/',
limit: 10240
}
}
},{
test:/\.scss$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
//表明前面要先走sass-loader和postcss-loader
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
},{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [new HtmlWebpackPlugin({
//表明要引用哪一个模板
template: 'src/index.html'
}),new CleanWebpackPlugin(['dist'])
],
// 输出,表明webpack应该怎么输出
output: {
publicPath: '/',
//用[]可以生成多个文件
filename: '[name].js',
// 指打包后的文件要放在哪个文件下
path: path.resolve(__dirname, 'dist')
}
}
3. 开发环境webpack.dev.js
抽离完 common
代码之后,现在我们来编写 webpack.dev.js
文件。具体代码如下:
const webpack = require('webpack');
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const devConfig = {
mode:'production',
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: './dist',
// 当运行完npm run start时,会自动的帮我们打开浏览器
open: true,
port: 8080,
// 让我们的webpackDevServer开启hotModuleReplacement这样子的功能
hot: true,
// 即便HMR没有生效,也不让浏览器自动刷新
hotOnly: true
},
plugins: [
//热模块更新
new webpack.HotModuleReplacementPlugin()
],
optimization: {
usedExports: true
}
}
module.exports = merge(commonConfig, devConfig)
4. 生产环境webpack.prod.js
继续,我们来编写抽离后的 prod
代码。具体代码如下:
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const prodConfig = {
mode:'development',
devtool: 'cheap-module-source-map'
}
module.exports = merge(commonConfig, prodConfig)
到这里,大家对比上面三个文件的代码可以发现,这样的代码抽离使得我们的项目结构变得更为清晰了。
5. 运行项目package.json
上面配置完成之后,我们现在要来想一下,想要运行开发环境和生产环境不用的配置,是不是应该把运行命令也给区分开来。因此,我们对 package.json
文件做出以下配置:
{
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
}
}
通过以上配置,那么我们就可以通过命令 npm run dev
和 npm run build
来运行项目,以此来区分项目是开发环境还是生产环境。
同时,如果我们想要在控制台更直观的看到报错信息,那么在开发环境的情况下,我们可以不用 webpack-dev-server
来运行,可以直接用用 webpack
来运行。具体代码如下:
{
"scripts": {
"dev-server": "webpack --config webpac.dev.js",
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
}
}
这样,我们就可以通过 npm run dev-build
,来使用 webpack
来运行项目。
⚽三、Webpack和Code Splitting、SplitChunksPlugin
1. 代码分割-Code Splitting
有时候,我们可能会遇到一个业务逻辑里面有上万行代码,那么这上万行代码打包后,全部就丢到 main.js
文件里面了,这样大的文件,会使得整个项目的加载速度会变得很是缓慢。因此,我们就需要用到代码分割Code Splitting来解决这件事情。
我们在 webpack.common.js
中进行配置。具体代码如下:
module.exports = {
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
通过以上代码我们可以得知,通过使用 optimization
中的 splitChunks
,达到了代码分割的效果。
那使用这个配置之后, webpack
想要做的事情是什么呢?
事实上,使用 splitChunks
之后,那么当 webpack
遇到公用的类库时,会帮我们自动地打包生成一个新的文件,之后再把其余的业务逻辑拆分到另外一个文件中去。
值得注意的是,公用类库不管是以同步的方式还是以异步的方式进行加载, webpack
都能够帮我们进行代码分割。
2. 引例阐述-SplitChunksPlugin
上面我们讲到了 webpack
的代码分割,那么实际上, webpack
的代码分割,其底层实现原理所使用的是 splitChunksPlugin
这个插件。接下来我们来讲一下这个插件。
在没有用 SplitChunksPlugin
这个插件之前,如果我们异步引入一个库,那么 webpack
给其打包后的文件名将会命名为 0.js
、 1.js
和 ......
。
我们现在希望在做代码分割时, webpack
能给我们的第三方库进行自定义命名,这又该怎么处理呢?
3. 实现方式-SplitChunksPlugin
首先我们对引入的库前面,添加 webpackChunkName
配置。具体代码如下:
function getComponent() {
return import(/\*webpackChunkName:"lodash"\*/'lodash').then(({ default: \_ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Monday', 'Tuesday'], '\_');
return element;
})
}
getComponent().then(element => {
document.body.appendChild(element);
})
/*webpackChunkName:"lodash"*/
这句话想要表明的意思为:当我们异步的引入 lodash
这个库并且想要做代码分割时,即当我们给 webpack
进行打包时,给其起名为 lodash
。
上面这个配置知识第一步,接下来我们要来安装并使用一个动态引入的插件。具体代码如下:
安装插件:
npm install --save-dev @babel/plugin-syntax-dynamic-import
在 .babelrc
下引入:
{
// plugins: ["dynamic-import-webpack"] 非官方支持插件
plugins: ["@babel/plugin-syntax-dynamic-import"]
}
配置 webpack.common.js
:
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: false,
default: false
}
}
},
}
4. SplitChunksPlugin配置参数
接下来我们再来看关于 SplitChunksPlugin
的一些常用配置。具体代码如下:
module.exports = {
optimization: {
splitChunks: {
/\*使用async时,只对异步代码进行代码分割;
使用all时,对同步和异步代码同时进行代码分割;
使用initial时,表示对同步代码进行代码分割\*/
chunks: 'all',
//大于30kb时,做代码分割
minSize: 30000,
//表明代码分割后文件最大的大小,如果超过了则会继续进行拆分;有一些文件如果拆分不了则此配置想基本就没啥用了
maxSize: 0,
minRemainingSize: 0,
//至少有两个块被使用了才会被提取
minChunks: 2,
//表示同时加载的模块数,最多是5个
/\*比如我们引入了10个类库,那么我们会做10次代码分割。
而这个时候我们将此参数填为5,那么webpack在打包时会将前10个库给我们生成5个js文件,
之后的就不会再做代码分割了,全部丢到一个文件里面去\*/
maxAsyncRequests: 5,
//入口文件做代码分割最多只能分割成3个js文件,超过3个就不会再做代码分割了
maxInitialRequests: 3,
//文件生成时的中间符号
automaticNameDelimiter: '~',
//让defaultVendors和default中的文件名有效
name: true,
enforceSizeThreshold: 50000,
//当打包同步代码时,cacheGroups
cacheGroups: {
defaultVendors: {
//检测你引入的库,查询是否是在node\_module下的
test: /[\\/]node\_modules[\\/]/,
priority: -10,
//确定是在node\_modules下后,将其进行打包,并命名为vendors.js
filename: 'vendors.js'
},
//对非第三方库的代码做代码分割
default: {
priority: -20,
reuseExistingChunk: true,
filename: 'common.js'
}
},
}
}
}
🏐四、打包分析,Preloading,Prefetching
1. 打包分析
打包分析指的是,当我们使用 webpack
来进行代码打包之后,我们可以借助打包分析的一些工具,来对我们打包生成的文件进行一定的分析,之后来看其打包的是否合理。那么如何进行打包分析呢?
我们要用到一个 github
的第三方仓库,戳此链接进入~
了解完文档该库的内容后,接下来我们要对 package.json
进行配置。具体代码如下:
{
"scripts": {
"dev-build": "webpack --profile --json > stats.json --config ./build/webpack.dev.js",
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
}
}
通过上面的代码,我们可以分析:在 --config
前面加上配置 --profile --json > stats.json
,意思为 webpack
打包后会生成打包分析文件,这个文件叫做 stats.json
,同时, --json
表示的意思为 stats.json
文件的格式是一个 json
格式的。
给大家的福利
零基础入门
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
因篇幅有限,仅展示部分资料
网络安全面试题
绿盟护网行动
还有大家最喜欢的黑客技术
网络安全源码合集+工具包
所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
行动
还有大家最喜欢的黑客技术
网络安全源码合集+工具包
所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
[外链图片转存中…(img-gD5v8a8p-1713419541486)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!