什么是CDN
介绍:CDN(内容分发网络)优化是一种用于加速网站或应用程序内容传输的技术策略。CDN将站点的静态资源(如图像、CSS文件、JavaScript文件等)分布在全球各个服务器节点上,使用户能够从离他们地理位置更近的服务器获取内容,从而提高加载速度和性能。
CDN优化的几个主要方面:
- 静态资源缓存:CDN将静态资源缓存在离用户更近的服务器上,这样用户在请求资源时可以从离他们最近的服务器获取,减少网络延迟和带宽消耗。
- 负载均衡:CDN使用负载均衡算法将用户的请求分配到最优的服务器节点上,以避免某些节点过载而影响性能。
- 边缘缓存:CDN将静态资源缓存在分布在全球各地的边缘服务器上,这些服务器位于用户和源服务器之间,可以更快地响应用户请求,减少网络距离。
- 动态内容加速:除了静态资源,CDN还可以缓存和加速动态生成的内容。CDN可以缓存动态内容的片段或完整页面,并使用高速缓存服务器提供快速响应。
- 压缩和优化:CDN可以对静态资源进行压缩和优化,以减小文件大小并提高加载速度。例如,可以压缩CSS和JavaScript文件、对图像进行压缩和优化,以减少传输时间和带宽消耗。
- 安全性增强:CDN可以提供一些安全功能,如防御DDoS攻击、提供SSL加密等,以保护网站或应用程序免受恶意行为的影响。
为什么要使用CDN
随着项目的功能增多,项目变大,而使用的第三方库也可能随之变多,最后通过打包会将这些第三方库都打包到一个js文件中,导致这个文件非常的大,加载时的速度慢。而使用CDN可以将这些第三方库缓存在离自己更近的服务器上,用户在请求资源时可以从离自己比较近的服务器上获取,减少了网络延时以及自己服务器宽带的消耗。
演示不使用CDN和使用CDN的区别
注意:下面的演示并没有用vue脚手架创建项目,而是用自己搭的webpack演示的,但也差不多。
测试使用的第三方库有:
npm install vue@2.6.14 vuex@3.5.1 vue-router@3.2.0 axios@1.3.6 element-ui@2.15.13
// src/index.js
import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
import vuex from 'vuex';
import Element from 'element-ui';
import axios from 'axios';
console.log(VueRouter, vuex, Element, axios);
new Vue({
render: (h) => h(App),
}).$mount('#app');
修改package.json
"scripts": {
"build": "webpack --config ./webpack.config.js"
},
配置webpack
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].[contenthash:4].js',
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './index.html'),
}),
],
};
直接打包
npm run build
然后通过Live server运行打包后的index.html,并将浏览器的Disable cache开启并将网络切换到Fast 3G,运行结果如下图所示:
使用CDN首先需要对webpack进行修改,我的配置如下:
- externals:防止将某些
import的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖。- 注意externals对象中的键名对应包名,值对应包的全局变量
- 一般只有生产环境时才会用到CDN,开发环境一般不用
- 免费开源的CDN网站:Bootcdn、jsdelivr
// webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
// prettier-ignore
const externals = {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios',
'element-ui': 'Element',
};
const cdn = {
dev: {
css: ['https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/theme-chalk/index.min.css'],
js: [],
},
build: {
css: ['https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/theme-chalk/index.min.css'],
js: [
'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/index.min.js',
'https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js',
'https://cdn.bootcdn.net/ajax/libs/vue-router/3.2.0/vue-router.min.js',
'https://cdn.bootcdn.net/ajax/libs/vuex/3.5.1/vuex.min.js',
'https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js',
],
},
};
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].[contenthash:4].js',
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader'],
},
],
},
externals: externals,
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './index.html'),
cdn: cdn.build,
}),
],
};
在准备的HTML文件中读取webpack中事前配置好的cdn,并使用EJS语法进行动态插入script标签引入外部资源。具体如下:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<% for (var i in htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
<% for (var i in htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
</head>
<body>
<div id="app"></div>
<div class="img-container"></div>
<img class="img" />
</body>
</html>
将安装到node_modules中的包移除
npm uninstall vue vuex vue-router axios element-ui
打包后运行index.html对比之前要快了不少