记录--从原理分析vue开发环境搭建的全部过程
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
平时大家开发vue项目的时候,相信大部分人都是使用 vue-cli
脚手架生成的项目架构,然后 npm run install
安装依赖,npm run serve
启动项目然后就开始写业务代码了。
但是对项目里的webpack
封装和配置了解的不清楚,容易导致出问题不知如何解决,或者不会通过webpack
去扩展新功能。
该篇文章主要是想告诉兄弟们,如何一步一步的通过 webpack4
来搭建自己的vue
开发环境
首先我们要知道 vue-cli
生成的项目,帮我们配置好了哪些功能?
ES6
代码转换成ES5
代码scss/sass/less/stylus
转css
.vue
文件转换成js
文件- 使用
jpg
、png
,font
等资源文件 - 自动添加css各浏览器产商的前缀
- 代码热更新
- 资源预加载
- 每次构建代码清除之前生成的代码
- 定义环境变量
- 区分开发环境打包跟生产环境打包
- ....
1. 搭建 webpack
基本环境
该篇文章并不会细讲 webpack
是什么东西,如果还不是很清楚的话,可以先去看看 webpack官网
简单的说,webpack
是一个模块打包机,可以分析你的项目依赖的模块以及一些浏览器不能直接运行的语言jsx
、vue
等转换成 js
、css
文件等,供浏览器使用。
1.1 初始化项目
在命令行中执行 npm init
然后一路回车就行了,主要是生成一些项目基本信息。最后会生成一个 package.json
文件
npm init
1.2 安装webpack
1.3 写点小代码测试一下webpack
是否安装成功了
新建一个src
文件夹,然后再建一个main.js
文件
// src/main.js
console.log('hello webpack')
然后在 package.json 下面加一个脚本命令
然后运行该命令
npm run serve
如果在 dist 目录下生成了一个main.js
文件,则表示webpack
工作正常
2. 开始配置功能
- 新建一个
build
文件夹,用来存放webpack
配置相关的文件 - 在
build
文件夹下新建一个webpack.config.js
,配置webpack
的基本配置 - 修改
webpack.config.js
配置
- 修改
package.json
文件,将之前添加的serve
修改为
"serve": "webpack ./src/main.js --config ./build/webpack.config.js"
2.1 配置 ES6/7/8
转 ES5
代码
- 安装相关依赖
npm install babel-loader @babel/core @babel/preset-env
- 修改
webpack.config.js
配置
- 在项目根目录添加一个
babel.config.js
文件
- 然后执行
npm run serve
命令,可以看到 ES6代码被转成了ES5代码了
2.1.1 ES6/7/8 Api
转es5
babel-loader
只会将 ES6/7/8语法转换为ES5语法,但是对新api并不会转换。
我们可以通过 babel-polyfill 对一些不支持新语法的客户端提供新语法的实现
- 安装
npm install @babel/polyfill
- 修改
webpack.config.js
配置
在 entry
中添加 @babel-polyfill
2.1.2 按需引入polyfill
2.1.2 和 2.1.1 只需要配置一个就行
修改时间 2019-05-05、 来自评论区 兮漫天 的提醒
- 安装相关依赖
npm install core-js@2 @babel/runtime-corejs2 -S
- 修改 babel-config.js
配置了按需引入 polyfill
后,用到es6
以上的函数,babel
会自动导入相关的polyfill
,这样能大大减少 打包编译后的体积
2.2 配置 scss
转 css
在没配置 css
相关的 loader
时,引入scss
、css
相关文件打包的话,会报错
- 安装相关依赖
npm install sass-loader dart-sass css-loader style-loader -D
sass-loader
, dart-sass
主要是将 scss/sass 语法转为css
css-loader
主要是解析 css 文件
style-loader
主要是将 css 解析到 html
页面 的 style
上
- 修改
webpack.config.js
配置
2.3 配置 postcss 实现自动添加css3前缀
- 安装相关依赖
npm install postcss-loader autoprefixer -D
- 修改
webpack.config.js
配置
- 在项目根目录下新建一个
postcss.config.js
2.3 使用 html-webpack-plugin
来创建html页面
使用 html-webpack-plugin
来创建html页面,并自动引入打包生成的js
文件
- 安装依赖
npm install html-webpack-plugin -D
- 新建一个 public/index.html 页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
- 修改
webpack-config.js
配置
2.4 配置 devServer 热更新功能
通过代码的热更新功能,我们可以实现不刷新页面的情况下,更新我们的页面
- 安装依赖
npm install webpack-dev-server -D
- 修改
webpack.config.js
配置
通过配置 devServer
和 HotModuleReplacementPlugin
插件来实现热更新
2.5 配置 webpack 打包 图片、媒体、字体等文件
- 安装依赖
npm install file-loader url-loader -D
file-loader
解析文件url,并将文件复制到输出的目录中
url-loader
功能与 file-loader
类似,如果文件小于限制的大小。则会返回 base64
编码,否则使用 file-loader
将文件复制到输出的目录中
- 修改
webpack-config.js
配置 添加rules
配置,分别对 图片,媒体,字体文件进行配置
// build/webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {
// 省略其它配置 ...
module: {
rules: [
// ...
{
test: /\.(jpe?g|png|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
}
}
]
},
]
},
plugins: [
// ...
]
}
3. 让 webpack
识别 .vue
文件
- 安装需要的依赖文件
npm install vue-loader vue-template-compiler cache-loader thread-loader -D
npm install vue -S
vue-loader
用于解析.vue
文件
vue-template-compiler
用于编译模板
cache-loader
用于缓存loader
编译的结果
thread-loader
使用 worker
池来运行loader
,每个 worker
都是一个 node.js
进程。
- 修改
webpack.config.js
配置
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
// 指定打包模式
mode: 'development',
entry: {
// ...
},
output: {
// ...
},
devServer: {
// ...
},
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js'
},
},
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'cache-loader'
},
{
loader: 'thread-loader'
},
{
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
},
}
}
]
},
{
test: /\.jsx?$/,
use: [
{
loader: 'cache-loader'
},
{
loader: 'thread-loader'
},
{
loader: 'babel-loader'
}
]
},
// ...
]
},
plugins: [
// ...
new VueLoaderPlugin()
]
}
- 测试一下
- 在 src 新建一个 App.vue
// src/App.vue
<template>
<div class="App">
Hello World
</div>
</template> <script>
export default {
name: 'App', data() {
return {};
}
};
</script> <style lang="scss" scoped>
.App {
color: skyblue;
}
</style>
- 修改
main.js
import Vue from 'vue'
import App from './App.vue' new Vue({
render: h => h(App)
}).$mount('#app')
- 运行一下
npm run serve
4. 定义环境变量
通过 webpack
提供的DefinePlugin
插件,可以很方便的定义环境变量
plugins: [
new webpack.DefinePlugin({
'process.env': {
VUE_APP_BASE_URL: JSON.stringify('http://localhost:3000')
}
}),
]
5. 区分生产环境和开发环境
新建两个文件
webpack.dev.js
开发环境使用webpack.prod.js
生产环境使用webpack.config.js
公用配置开发环境与生产环境的不同
5.1 开发环境
- 不需要压缩代码
- 需要热更新
- css不需要提取到css文件
- sourceMap
- ...
5.2 生产环境
- 压缩代码
- 不需要热更新
- 提取css,压缩css文件
- sourceMap
- 构建前清除上一次构建的内容
- ...
- 安装所需依赖
npm i @intervolga/optimize-cssnano-plugin mini-css-extract-plugin clean-webpack-plugin webpack-merge copy-webpack-plugin -D
@intervolga/optimize-cssnano-plugin
用于压缩css代码mini-css-extract-plugin
用于提取css到文件中clean-webpack-plugin
用于删除上次构建的文件webpack-merge
合并webpack
配置copy-webpack-plugin
用户拷贝静态资源
5.3 开发环境配置
- build/webpack.dev.js
// build/webpack.dev.js
const merge = require('webpack-merge')
const webpackConfig = require('./webpack.config')
const webpack = require('webpack')
module.exports = merge(webpackConfig, {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
module: {
rules: [
{
test: /\.(scss|sass)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
},
{
loader: 'postcss-loader'
}
]
},
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development')
}
}),
]
})
- webpack.config.js
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
entry: {
// 配置入口文件
main: path.resolve(__dirname, '../src/main.js')
},
output: {
// 配置打包文件输出的目录
path: path.resolve(__dirname, '../dist'),
// 生成的 js 文件名称
filename: 'js/[name].[hash:8].js',
// 生成的 chunk 名称
chunkFilename: 'js/[name].[hash:8].js',
// 资源引用的路径
publicPath: '/'
},
devServer: {
hot: true,
port: 3000,
contentBase: './dist'
},
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js'
},
extensions: [
'.js',
'.vue'
]
},
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'cache-loader'
},
{
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
},
}
}
]
},
{
test: /\.jsx?$/,
loader: 'babel-loader'
}, {
test: /\.(jpe?g|png|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
}
}
]
},
]
},
plugins: [
new VueLoaderPlugin(), new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html')
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
}
5.4 生产环境配置
const path = require('path')
const merge = require('webpack-merge')
const webpack = require('webpack')
const webpackConfig = require('./webpack.config')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssnanoPlugin = require('@intervolga/optimize-cssnano-plugin');
/* clean-webpack-plugin 3.0 以上的版本需要使用对象结构 */
// const CleanWebpackPlugin = require('clean-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = merge(webpackConfig, {
mode: 'production',
devtool: '#source-map',
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors',
test: /[\\\/]node_modules[\\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
}
},
module: {
rules: [
{
test: /\.(scss|sass)$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
},
{
loader: 'postcss-loader'
}
]
},
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: 'production'
}
}),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
chunkFilename: 'css/[name].[contenthash:8].css'
}),
new OptimizeCssnanoPlugin({
sourceMap: true,
cssnanoOptions: {
preset: [
'default',
{
mergeLonghand: false,
cssDeclarationSorter: false
}
]
}
}),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../public'),
to: path.resolve(__dirname, '../dist')
}
]),
new CleanWebpackPlugin()
]
})
5.5 修改package.json
"scripts": {
"serve": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
6 打包分析
有的时候,我们需要看一下webpack打包完成后,到底打包了什么东西,
这时候就需要用到这个模块分析工具了 webpack-bundle-analyzer
- 安装依赖
npm install --save-dev webpack-bundle-analyzer
- 修改
webpack-prod.js
配置,在plugins
属性中新增一个插件
在开发环境中,我们是没必要进行模块打包分析的,所以我们将插件配置在了生产环境的配置项中
- 运行打包命令
npm run build
执行成功后会自动打开这个页面
7. 集成 VueRouter
,Vuex
- 首先是安装相关依赖
npm install vue-router vuex --save
7.1 集成 Vue-Router
- 新增视图组件 在
src
目录下新增两个视图组件src/views/Home.vue
和src/views/About.vue
// src/views/Home.vue
<template>
<div class="Home">
<h2>Home</h2>
</div>
</template> <script>
export default {
name: 'Home', data() {
return {};
}
};
</script> <style lang="scss" scoped>
</style>
About.vue
内容跟 Home.vue
差不多,将里面的 Home
换成 About
就OK了
- 新增路由配置文件
在 src
目录下新增一个 router/index.js
文件
// src/router/index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from '../views/Home';
import About from '../views/About';
Vue.use(VueRouter)
export default new VueRouter({
mode: 'hash',
routes: [
{
path: '/Home',
component: Home
},
{
path: '/About',
component: About
},
{
path: '*',
redirect: '/Home'
}
]
})
- 修改
main.js
文件
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router' new Vue({
router,
render: h => h(App)
}).$mount('#app')
- 修改
App.vue
组件
// App.vue
// 在 template 中添加
// src/App.vue
<template>
<div class="App">
Hello World
</div>
<div>
// router-link 组件 用来导航到哪个路由
<router-link to="/Home">go Home</router-link>
<router-link to="/About">go About</router-link>
</div>
<div>
// 用于展示匹配到的路由视图组件
<router-view></router-view>
</div>
</template> <script>
export default {
name: 'App', data() {
return {};
}
};
</script> <style lang="scss" scoped>
.App {
color: skyblue;
}
</style>
运行 npm run serve
命令,如没配置错误,是可以看到点击不同的路由,会切换到不同的路由视图
7.2 配置路由懒加载
在没配置路由懒加载的情况下,我们的路由组件在打包的时候,都会打包到同一个js
文件去,当我们的视图组件越来越多的时候,就会导致这个 js
文件越来越大。然后就会导致请求这个文件的时间变长,最终影响用户体验
- 安装依赖
npm install @babel/plugin-syntax-dynamic-import --save-dev
- 修改
babel.config.js
module.exports = {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage"
}
]
],
plugins: [
// 添加这个
'@babel/plugin-syntax-dynamic-import'
]
}
- 修改
router/index.js
路由配置文件
import Vue from 'vue'
import VueRouter from "vue-router";
Vue.use(VueRouter)
export default new VueRouter({
mode: 'hash',
routes: [
{
path: '/Home',
component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
// component: Home
},
{
path: '/About',
component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')
// component: About
},
{
path: '*',
redirect: '/Home'
}
]
})
- 运行命令
npm run build
查看是否生成了Home...js
文件 和About...js
文件
7.3 集成 Vuex
- 在
src
目录下新建一个store/index.js
文件
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
counter: 0
}
const actions = {
add: ({commit}) => {
return commit('add')
}
}
const mutations = {
add: (state) => {
state.counter++
}
}
const getters = {
getCounter (state) {
return state.counter
}
}
export default new Vuex.Store({
state,
actions,
mutations,
getters
})
- 修改
main.js
文件 导入vuex
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store' // ++
new Vue({
router,
store, // ++
render: h => h(App)
}).$mount('#app')
- 修改
App.vue
,查看 vuex 配置效果
// App.vue
<template>
<div class="App">
<div>
<router-link to="/Home">go Home</router-link>
<router-link to="/About">go About</router-link>
</div>
<div>
<p>{{getCounter}}</p>
<button @click="add">add</button>
</div>
<div>
<router-view></router-view>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'App',
data() {
return {};
},
computed: {
...mapGetters(['getCounter'])
},
methods: {
...mapActions(['add'])
}
};
</script>
<style lang="scss" scoped>
.App {
text-align: center;
color: skyblue;
font-size: 28px;
}
</style>
- 运行命令
npm run serve
当点击按钮的时候,可以看到我们的getCounter
一直在增加
8 总结
到目前为止,我们已经成功的自己搭建了一个 vue
开发环境,不过还是有一些功能欠缺的,有兴趣的小伙伴可以交流交流。在搭建过程中,还是会踩很多坑的。
如果还不熟悉 webpack 的话,建议自己搭建一次。可以让自己能深入的理解 vue-cli
替我们做了什么
本文转载于:
https://juejin.cn/post/6844903833160646663
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
记录--从原理分析vue开发环境搭建的全部过程的更多相关文章
- vue开发环境搭建及热更新
写这篇博客的目的是让广大的学者在初入Vue项目的时候少走些弯路,虽然现在有很多博客也有差不多的内容,但是博主在里面添加了一些学习时碰到的小问题.在阅读这篇博客之前,我先给大家推荐一篇文章<入门W ...
- express+mysql+vue开发环境搭建
最近开始做一个实验室资产管理系统,后台使用node.js的Express框架,前端使用vue,数据库使用mysql.在这里开始简单记录一下开发过程和遇到的问题. 今天要说的是express+mysql ...
- vue开发环境搭建Mac版
一.前言 要做一个移动端app,面对webapp最流行的三个技术React,angular,vue,三选一,如何选,可参考blog移动app技术选型,react,angular, vue, 下面是对 ...
- 【强烈推荐,超详细,实操零失误】node.js安装 + npm安装教程 + Vue开发环境搭建
node.js安装 + npm安装教程 + Vue开发环境搭建 [强烈推荐,超详细,实操零失误] 原博客园地址:https://www.cnblogs.com/goldlong/p/8027997.h ...
- 最全Vue开发环境搭建
前言 一直想去学Vue,不过一直找不到一个契机.然公司手机端用到了跨平台开发apicloud,里边涉及到Vue组件化开发,例如header和footer的封装,以及apicloud自定义的frame等 ...
- vue 开发系列(一) vue 开发环境搭建
概要 目前前端开发技术越来越像后台开发了,有一站式的解决方案. 1.JS包的依赖管理像MAVEN. 2.JS代码编译打包. 3.组件式的开发. vue 是一个前端的一站式的前端解决方案,从项目的初始化 ...
- 一 vue开发环境搭建
2016年,Vue同Angular.React形成三足鼎立的局面,让前端的开发者顾不暇接,今天我们就来了解一下Vue的环境搭建. 一.node.js安装: node.js:一种javascript的运 ...
- vscode vue开发环境搭建
以前仅了解过VUE但没有真正上手过,现在因为工作需要准备再近几个月里系统的学习一下这款超火的前端框架,希望大佬们指教. ---------------------------------------- ...
- 【VUE】Mac下vue 开发环境搭建,以及目录结构
1 安装Node.js 参看 node.js环境安装 http://www.cnblogs.com/richerdyoung/p/7265786.html 2 安装淘宝镜像 npm install ...
- 【Vue 学习笔记 一、Vue开发环境搭建】
搭建Vue的开发环境 1.首先安装Nodejs (因为我的系统是Windows的所以就选择第一个了,这个看个人的开发环境) 下载好后,然后一路确定,如果有更改安装目录的需求,就自己切换安装目录,由于 ...
随机推荐
- JS Leetcode 26. 删除有序数组中的重复项 题解分析,字典与快慢双指针
壹 ❀ 引 本题来自LeetCode26. 删除有序数组中的重复项,是一道简单题,题目描述如下: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组 ...
- zookeeper源码(08)请求处理及数据读写流程
ServerCnxnFactory 用于接收客户端连接.管理客户端session.处理客户端请求. ServerCnxn抽象类 代表一个客户端连接对象: 从网络读写数据 数据编解码 将请求转发给上层组 ...
- jupyter环境变量配置与启动
一.jupyter基础知识 1.基本概念 jupyter是基于网页的用于交互计算的应用程序.其可被应用于全过程计算:开发.文档编写.运行代码和展示结果. 编程时具有语法高亮,缩进,tab补全的功能. ...
- Qt5.15.0 升级至 Qt5.15.9 遇到的一些错误
按照之前我写的文章教程,可以很简单的编译出静态库(仅供学习交流) 编译 windows 上的 qt 静态库 编译出静态库后,替换旧版本的库,见我另一篇文章教程 VS2019 配置 QT 库 之所以没有 ...
- rpartition和partition按分割符分割
# rpartition 从目标字符串的末尾也就是右边开始搜索分割符,如果字符串包含指定的分割符 则返回一个3元的元组,第一个为分割符左边的子串,第二个为分割符本身, 第三个为分割符右边的字串. st ...
- kotlin协程异常处理之-try catch
kotlin协程小记 协程的async使用 kotlin协程异常处理之-try catch kotlin协程异常处理之-CoroutineExceptionHandler 一.try catch tr ...
- Java 理解“万事万物皆对象”+ 匿名对象的使用
1 /** 2 * 3 * @Description 4 * @author Bytezero·zhenglei! Email:420498246@qq.com 5 * @version 6 * @d ...
- Java //手动输入3个数,并从小到大排序
1 //手动输入3个数,并从小到大排序 2 //import java.util.Sanner; 3 4 System.out.println("请输入第一个数:"); 5 Sca ...
- TCP/IP协议 ------图解TCP/IP协议 全书知识点真理
一. 之前在网上大致浏览了<图解TCP/IP>这本书前面的几章,是日本人写的,没有细看,感觉写的很容易理解,但是最近又翻看网后面看到的时候感觉很多累赘的地方,不知道是翻译的问题,还是书本身 ...
- docker部署监控Prometheus+Grafana
目录 一.Prometheus简介 二.Prometheus基本原理 三.Prometheus架构图 四.Prometheus特性 五.Prometheus组件 六.Prometheus服务发现 七. ...