Webpack 构建优化项目实战:从入门到实践
2024/10/18 0:08:28
本文主要是介绍Webpack 构建优化项目实战:从入门到实践,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
本文深入探讨了如何使用Webpack进行构建优化项目,涵盖了从基础配置到高级优化的技术细节。通过具体示例,详细讲解了Tree Shaking、代码分割和懒加载等关键概念。此外,文章还提供了实战案例分享和常见问题解决方法。Webpack 构建优化项目实战帮助开发者构建高效的前端项目。
Webpack 是一个现代 JavaScript 应用程序的模块打包器。它主要用于将 JavaScript 文件打包成浏览器可以加载的格式。然而,Webpack 可以做更多,比如处理样式表、图片、字体等静态资源。Webpack 可以解析模块间的依赖关系,然后将这些模块打包成一个或多个文件,以供浏览器加载。通过使用模块化、代码分割、懒加载等技术,Webpack 可以帮助开发者构建出高效、可维护的项目。
Webpack 工作原理
- 模块解析:Webpack 从配置文件中指定的入口文件开始,解析并收集所有依赖的模块。
- 模块转换:对于每个模块,Webpack 会根据其类型(如 JavaScript 文件、CSS 文件等)应用相应的 loader 进行预处理。
- 输出生成:最终,Webpack 将处理后的模块按照指定的配置输出到目标文件中。
安装 Webpack 有多种方式,最常见的是通过 npm(Node.js 包管理器)进行全局安装或局部安装。
全局安装
全局安装 Webpack 可以避免每个项目都需要安装一次 Webpack 的麻烦。
npm install -g webpack
局部安装
局部安装 Webpack 是将 Webpack 安装在项目的 node_modules
目录下,并在 package.json
文件中定义它作为项目的开发依赖。
npm install --save-dev webpack
为了使用 Webpack,需要创建一个 webpack.config.js
文件。此文件定义了 Webpack 处理项目的一些基本配置。
基本配置文件
在项目根目录下创建 webpack.config.js
文件,并添加以下基本配置:
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } };
说明
- entry:定义项目的入口文件。
- output:定义输出文件的信息,包括文件名和路径。
entry 配置
entry 配置项用于指定项目的入口文件。这可以是一个字符串,也可以是一个对象。
entry: './src/index.js'
output 配置
output 配置项定义了 Webpack 如何输出打包后的文件。可以定义输出文件的名称、输出路径等。
output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }
示例
假设我们有一个简单的项目结构:
- src/ - index.js - dist/ - webpack.config.js
index.js
文件内容如下:
console.log('Hello, Webpack!');
在 webpack.config.js
中配置:
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } };
然后运行 webpack
命令,可以看到项目中的 index.js
文件被打包到 dist/bundle.js
文件中。
loader 定义
loader 是 Webpack 中用于转换模块的工具。loader 可以将文件从一种格式转换为另一种格式,例如将 .scss
文件转换为 .css
文件。
安装 loader
以 babel-loader
为例,它用来转换 ES6+ 特性到 ES5 代码。
npm install --save-dev babel-loader @babel/core @babel/preset-env
配置 loader
在 webpack.config.js
文件中配置 loader。
module.exports = { module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } } ] } };
示例
假设我们有一个使用 ES6 语法的文件 src/index.js
:
// src/index.js function add(a, b) { return a + b; } console.log(add(1, 2));
在 webpack.config.js
中配置 babel-loader
:
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } } ] } };
运行 webpack
命令,可以看到 src/index.js
文件被转换为 ES5 代码后输出到 dist/bundle.js
文件中。
plugin 定义
plugin 是 Webpack 的扩展点,可以注册在 webpack 的生命周期中任意节点的钩子,如优化代码、生成源码地图等。
安装 plugin
以 HtmlWebpackPlugin
为例,它用于根据 webpack 的输出生成 HTML 文件。
npm install --save-dev html-webpack-plugin
配置 plugin
在 webpack.config.js
文件中配置 plugin。
const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] };
示例
假设我们有一个简单的 src/index.html
文件:
<!-- src/index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Webpack App</title> </head> <body> <div id="app"></div> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="bundle.js"></script> </body> </html>
在 webpack.config.js
中配置 HtmlWebpackPlugin
:
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] };
运行 webpack
命令,可以看到不仅打包了 JavaScript 文件,还根据 src/index.html
生成了一个 dist/index.html
文件,包含打包后的 bundle.js
文件路径。
构建一个简单的 Web 应用,包括 HTML 文件、React 组件、CSS 样式等。
项目结构
- src/ - index.html - components/ - App.js - App.css - webpack.config.js - package.json
安装依赖
npm install --save react react-dom npm install --save-dev webpack webpack-cli html-webpack-plugin babel-loader @babel/core @babel/preset-env @babel/preset-react
示例代码
src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Webpack App</title> <link rel="stylesheet" href="components/App.css"> </head> <body> <div id="app"></div> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="bundle.js"></script> </body> </html>
src/components/App.js
import React from 'react'; function App() { return ( <div className="app"> <h1>Hello, Webpack!</h1> </div> ); } export default App;
src/components/App.css
.app { padding: 20px; border: 1px solid #ccc; border-radius: 5px; background-color: #f5f5f5; }
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'] } } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] };
说明
- entry: 指定项目的入口文件路径。
- output: 定义打包后的文件名及输出路径。
- module.rules: 用于定义不同的 loader 规则。
- plugins: 插件配置,用于生成 HTML 文件。
动态加载
动态加载指的是在运行时根据需要加载模块。这可以使用 import()
语法来实现,它返回一个 Promise,适用于按需加载。
示例代码
修改 src/index.js
:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; ReactDOM.render(<App />, document.getElementById('app'));
代码分割
代码分割是将应用程序分割为多个小的代码块,使它们可以按需加载。使用 import()
语法可以实现代码分割。
配置文件
在 webpack.config.js
中启用代码分割:
module.exports = { // ... 其他配置 module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'] } } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ], optimization: { runtimeChunk: 'single', splitChunks: { chunks: 'all' } } };
示例代码
在 src/components/App.js
中添加一个动态加载的组件:
import React from 'react'; import LazyComponent from './LazyComponent'; function App() { return ( <div className="app"> <h1>Hello, Webpack!</h1> <LazyComponent /> </div> ); } export default App;
在 src/components/LazyComponent.js
中定义一个简单的组件:
import React from 'react'; function LazyComponent() { return <h2>This is a lazy loaded component!</h2>; } export default LazyComponent;
在 src/index.js
中动态加载 LazyComponent
:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; function loadComponent() { return import('./components/LazyComponent').then(({ LazyComponent }) => { ReactDOM.render(<LazyComponent />, document.getElementById('lazy-component')); }); } loadComponent(); ReactDOM.render(<App />, document.getElementById('app'));
运行 webpack
命令,可以看到 Webpack 会将代码分割成多个小块,按需加载。
Tree Shaking 是一种代码优化技术,用于在打包过程中去除未使用的代码。它可以在构建时移除未使用的模块、函数和变量。
说明
- Webpack 本身支持 Tree Shaking,但需要确保引入的库也支持 Tree Shaking。
- 使用 ES6 模块(
.mjs
或.js
文件)可以启用 Tree Shaking。
配置文件
在 webpack.config.js
中确保使用 ES6 模块:
module.exports = { // ... 其他配置 resolve: { extensions: ['.js', '.jsx'] } };
示例代码
在 src/index.js
中引入一个未使用的模块:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; import { unusedFunction } from './unusedModule'; unusedFunction(); // 使用 ReactDOM.render(<App />, document.getElementById('app'));
在 src/unusedModule.js
中定义一个未使用的函数:
export function unusedFunction() { console.log('This is an unused function.'); }
运行 webpack
命令,未使用的 unusedFunction
将不会出现在最终的输出文件中。
代码分割技术
代码分割是将应用程序分割为多个小的代码块,使它们可以按需加载。这可以使用 Webpack 的 splitChunks
配置来实现。
示例代码
在 webpack.config.js
中启用代码分割:
module.exports = { // ... 其他配置 optimization: { runtimeChunk: 'single', splitChunks: { chunks: 'all' } } };
示例代码
假设我们有一个 src/utils/math.js
文件:
export function add(a, b) { return a + b; } export function subtract(a, b) { return a - b; }
在 src/index.js
中引入这些函数:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; import { add, subtract } from './utils/math'; console.log(add(1, 2)); console.log(subtract(3, 1)); ReactDOM.render(<App />, document.getElementById('app'));
运行 webpack
命令,utils/math.js
将被分割成一个单独的代码块。
懒加载技术
懒加载是一种按需加载模块的技术,通过使用 import()
语法来实现。
示例代码
在 src/index.js
中动态加载一个模块:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; function loadComponent() { return import('./components/LazyComponent').then(({ LazyComponent }) => { ReactDOM.render(<LazyComponent />, document.getElementById('lazy-component')); }); } loadComponent(); ReactDOM.render(<App />, document.getElementById('app'));
示例代码
假设我们有一个 src/components/LazyComponent.js
文件:
import React from 'react'; function LazyComponent() { return <h2>This is a lazy loaded component!</h2>; } export default LazyComponent;
运行 webpack
命令,LazyComponent
将在需要时才被加载。
自定义 loader
自定义 loader 可以根据特定需求转换文件。
例子:自定义 loader
创建一个简单的 loader 文件 custom-loader.js
:
module.exports = function(source) { return source.replace('Hello', 'Hey'); };
在 webpack.config.js
中配置自定义 loader:
module.exports = { module: { rules: [ { test: /\.txt$/, use: { loader: path.resolve(__dirname, './custom-loader') } } ] } };
自定义 plugin
自定义 plugin 可以在 Webpack 的构建过程中插入自定义逻辑。
例子:自定义 plugin
创建一个简单的 plugin 文件 custom-plugin.js
:
class CustomPlugin { apply(compiler) { compiler.hooks.emit.tap('CustomPlugin', compilation => { console.log('Custom Plugin is working!'); }); } } module.exports = CustomPlugin;
在 webpack.config.js
中配置自定义 plugin:
const CustomPlugin = require('./custom-plugin'); module.exports = { plugins: [ new CustomPlugin() ] };
配置环境变量
环境变量可以用于区分开发环境和生产环境。
示例
在项目根目录中创建 .env
文件:
NODE_ENV=development API_URL=http://api.example.com
安装 dotenv
插件:
npm install --save-dev dotenv
在 webpack.config.js
中配置环境变量:
require('dotenv').config(); module.exports = { // ... 其他配置 plugins: [ new webpack.DefinePlugin({ 'process.env': JSON.stringify(process.env) }) ] };
使用环境变量
在代码中使用环境变量:
console.log(process.env.NODE_ENV); console.log(process.env.API_URL);
模块解析配置
模块解析配置可以自定义模块的查找规则。
示例
在 webpack.config.js
中配置模块解析:
module.exports = { resolve: { modules: ['node_modules', 'custom_modules'], alias: { '@utils': path.resolve(__dirname, 'src/utils') }, extensions: ['.js', '.jsx', '.json'] } };
示例代码
假设我们有一个文件结构:
- src/ - utils/ - math.js - webpack.config.js
在 webpack.config.js
中配置别名:
module.exports = { // ... 其他配置 resolve: { alias: { '@utils': path.resolve(__dirname, 'src/utils') } } };
在代码中使用别名:
import { add } from '@utils/math'; console.log(add(1, 2));
案例一:SPA 应用
使用 Webpack 构建一个单页面应用(SPA),包括路由、组件等。
项目结构
- src/ - index.html - App.js - components/ - Header.js - Footer.js - routes/ - Home.js - About.js - styles/ - App.css - webpack.config.js - package.json
安装依赖
npm install --save react react-dom react-router-dom npm install --save-dev webpack webpack-cli html-webpack-plugin babel-loader @babel/core @babel/preset-env @babel/preset-react
示例代码
src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SPA Webpack App</title> <link rel="stylesheet" href="styles/App.css"> </head> <body> <div id="root"></div> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="bundle.js"></script> </body> </html>
src/App.js
import React from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import Header from './components/Header'; import Footer from './components/Footer'; import Home from './routes/Home'; import About from './routes/About'; function App() { return ( <Router> <Header /> <Switch> <Route path="/" exact component={Home} /> <Route path="/about" component={About} /> </Switch> <Footer /> </Router> ); } export default App;
src/components/Header.js
import React from 'react'; function Header() { return <header>Header</header>; } export default Header;
src/components/Footer.js
import React from 'react'; function Footer() { return <footer>Footer</footer>; } export default Footer;
src/routes/Home.js
import React from 'react'; function Home() { return <h1>Home</h1>; } export default Home;
src/routes/About.js
import React from 'react'; function About() { return <h1>About</h1>; } export default About;
src/styles/App.css
header { background-color: #4a148c; color: white; padding: 10px; text-align: center; } footer { background-color: #4a148c; color: white; padding: 10px; text-align: center; }
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'] } } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ], optimization: { runtimeChunk: 'single', splitChunks: { chunks: 'all' } } };
案例二:多页面应用
使用 Webpack 构建一个多页面应用,包括多个入口文件。
项目结构
- src/ - index.html - about.html - App.js - components/ - Header.js - Footer.js - pages/ - Home.js - About.js - styles/ - App.css - webpack.config.js - package.json
安装依赖
npm install --save react react-dom npm install --save-dev webpack webpack-cli html-webpack-plugin babel-loader @babel/core @babel/preset-env @babel/preset-react
示例代码
src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Home Webpack App</title> <link rel="stylesheet" href="styles/App.css"> </head> <body> <div id="root"></div> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="home.bundle.js"></script> </body> </html>
src/about.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>About Webpack App</title> <link rel="stylesheet" href="styles/App.css"> </head> <body> <div id="root"></div> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="about.bundle.js"></script> </body> </html>
src/App.js
import React from 'react'; function App() { return ( <div className="app"> <Header /> <Pages /> <Footer /> </div> ); } export default App;
src/components/Header.js
import React from 'react'; function Header() { return <header>Header</header>; } export default Header;
src/components/Footer.js
import React from 'react'; function Footer() { return <footer>Footer</footer>; } export default Footer;
src/pages/Home.js
import React from 'react'; function Home() { return <h1>Home</h1>; } export default Home;
src/pages/About.js
import React from 'react'; function About() { return <h1>About</h1>; } export default About;
src/styles/App.css
.app { display: flex; flex-direction: column; height: 100vh; } header { background-color: #4a148c; color: white; padding: 10px; text-align: center; } footer { background-color: #4a148c; color: white; padding: 10px; text-align: center; }
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { home: './src/index.js', about: './src/about.js' }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'] } } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', filename: 'index.html', chunks: ['home'] }), new HtmlWebpackPlugin({ template: './src/about.html', filename: 'about.html', chunks: ['about'] }) ] };
案例三:前端构建工具链
使用 Webpack 集成其他前端构建工具,如 Babel、Sass、PostCSS 等。
项目结构
- src/ - index.html - App.js - components/ - Header.js - Footer.js - styles/ - styles.scss - webpack.config.js - package.json
安装依赖
npm install --save react react-dom npm install --save-dev webpack webpack-cli html-webpack-plugin babel-loader @babel/core @babel/preset-env @babel/preset-react sass sass-loader postcss-loader autoprefixer
示例代码
src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Webpack App</title> <link rel="stylesheet" href="styles/main.css"> </head> <body> <div id="root"></div> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="bundle.js"></script> </body> </html>
src/App.js
import React from 'react'; function App() { return ( <div className="app"> <Header /> <Footer /> </div> ); } export default App;
src/components/Header.js
import React from 'react'; function Header() { return <header>Header</header>; } export default Header;
src/components/Footer.js
import React from 'react'; function Footer() { return <footer>Footer</footer>; } export default Footer;
src/styles/styles.scss
.app { display: flex; flex-direction: column; height: 100vh; } header { background-color: #4a148c; color: white; padding: 10px; text-align: center; } footer { background-color: #4a148c; color: white; padding: 10px; text-align: center; }
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'] } } }, { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader', 'postcss-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] };
- 打包失败:检查配置文件是否正确,特别是
entry
和module.rules
配置。 - 代码不生效:确保文件路径正确,检查 loader 和 plugin 是否正确配置。
- 环境变量配置:确保
dotenv
已安装并正确配置。
- 模块化与代码分割:利用 Webpack 的模块化和代码分割特性,可以提高应用的加载速度和可维护性。
- 动态加载:使用
import()
语法实现动态加载,可以优化应用的性能。 - 插件与 loader:合理使用 Webpack 插件和 loader,可以简化构建流程并增强功能。
- Tree Shaking:启用 Tree Shaking 可以减少未使用的代码,提高应用的性能。
通过以上内容,希望你能全面了解 Webpack 的基本使用和高级配置,从而构建出高效、可维护的前端项目。
这篇关于Webpack 构建优化项目实战:从入门到实践的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-20Mycat教程:新手快速入门指南
- 2024-11-20WebSocket入门:轻松掌握WebSocket基础
- 2024-11-19WebSocket入门指南:轻松搭建实时通信应用
- 2024-11-19Nacos安装资料详解:新手入门教程
- 2024-11-19Nacos安装资料:新手入门教程
- 2024-11-19升级 Gerrit 时有哪些注意事项?-icode9专业技术文章分享
- 2024-11-19pnpm是什么?-icode9专业技术文章分享
- 2024-11-19将文件或目录压缩并保留到指定的固定目录怎么实现?-icode9专业技术文章分享
- 2024-11-19使用 tar 命令压缩文件并且过滤掉某些特定的目录?-icode9专业技术文章分享
- 2024-11-18Nacos安装入门教程