当前位置: 首页 > article >正文

前端工程化新方法:别再手动配置了

前端工程化新方法别再手动配置了什么是前端工程化新方法前端工程化新方法是指在前端开发中随着技术的发展出现的新的工程化技术和方法。别以为工程化只是配置 Webpack那是十年前的玩法了。为什么需要关注前端工程化新方法开发效率提高开发效率减少重复工作代码质量提高代码质量减少错误团队协作便于团队协作统一开发规范部署效率提高部署效率减少部署时间可维护性提高代码可维护性降低维护成本前端工程化新方法1. 现代构建工具使用现代构建工具提高构建效率。// Vite 配置 // vite.config.js import { defineConfig } from vite; import react from vitejs/plugin-react; import vue from vitejs/plugin-vue; import svelte from sveltejs/vite-plugin-svelte; export default defineConfig({ plugins: [react()], // 或 vue() 或 svelte() build: { outDir: dist, minify: terser, sourcemap: true }, server: { port: 3000, open: true, proxy: { /api: { target: http://localhost:8000, changeOrigin: true } } } }); // esbuild 配置 // esbuild.config.js const esbuild require(esbuild); esbuild.build({ entryPoints: [src/index.js], bundle: true, minify: true, sourcemap: true, outfile: dist/bundle.js }); // Rollup 配置 // rollup.config.js import resolve from rollup/plugin-node-resolve; import commonjs from rollup/plugin-commonjs; import babel from rollup/plugin-babel; export default { input: src/index.js, output: { file: dist/bundle.js, format: esm }, plugins: [ resolve(), commonjs(), babel({ babelHelpers: bundled }) ] };2. 包管理器使用现代包管理器提高依赖管理效率。// npm 配置 // package.json { name: frontend-project, version: 1.0.0, scripts: { dev: vite, build: vite build, preview: vite preview, lint: eslint ., test: jest }, dependencies: { react: ^18.2.0, react-dom: ^18.2.0 }, devDependencies: { vitejs/plugin-react: ^4.2.1, eslint: ^8.57.0, eslint-plugin-react: ^7.34.1, jest: ^29.7.0, vite: ^5.2.0 } } // yarn 配置 // .yarnrc.yml nodeLinker: node-modules // pnpm 配置 // pnpm-workspace.yaml packages: - packages/* - apps/*3. 代码规范使用现代代码规范工具提高代码质量。// ESLint 配置 // .eslintrc.js module.exports { env: { browser: true, es2021: true, node: true }, extends: [ eslint:recommended, plugin:react/recommended, prettier ], parserOptions: { ecmaVersion: 12, sourceType: module, ecmaFeatures: { jsx: true } }, plugins: [ react ], rules: { react/prop-types: off, no-console: warn } }; // Prettier 配置 // .prettierrc { printWidth: 80, tabWidth: 2, useTabs: false, semi: true, singleQuote: true, trailingComma: es5, bracketSpacing: true, jsxBracketSameLine: false, arrowParens: avoid } // TypeScript 配置 // tsconfig.json { compilerOptions: { target: es5, lib: [dom, dom.iterable, esnext], allowJs: true, skipLibCheck: true, esModuleInterop: true, allowSyntheticDefaultImports: true, strict: true, forceConsistentCasingInFileNames: true, noFallthroughCasesInSwitch: true, module: esnext, moduleResolution: node, resolveJsonModule: true, isolatedModules: true, noEmit: true, jsx: react-jsx }, include: [src] }4. 版本控制使用现代版本控制工具提高代码管理效率。// Git 配置 // .gitconfig [user] name Your Name email your.emailexample.com [core] editor code --wait [alias] co checkout br branch ci commit st status lg log --oneline --graph // .gitignore # Dependencies node_modules/ # Build output dist/ build/ # Environment variables .env .env.local .env.development.local .env.test.local .env.production.local # Editor directories and files .vscode/ .idea/ *.suo *.ntvs* *.njsproj *.sln *.sw? // Git Hooks // .husky/pre-commit #!/bin/sh . $(dirname $0)/_/husky.sh npm run lint npm run test // .husky/commit-msg #!/bin/sh . $(dirname $0)/_/husky.sh npx commitlint --edit $15. 自动化测试使用现代自动化测试工具提高代码质量。// Jest 配置 // jest.config.js module.exports { testEnvironment: jsdom, setupFilesAfterEnv: [./src/setupTests.js], collectCoverageFrom: [ src/**/*.{js,jsx,ts,tsx}, !src/**/*.d.ts ], coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } } }; // React 测试示例 // src/__tests__/App.test.js import { render, screen, fireEvent } from testing-library/react; import App from ../App; test(renders learn react link, () { render(App /); const linkElement screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); }); test(handles button click, () { render(App /); const buttonElement screen.getByText(Click me); fireEvent.click(buttonElement); const messageElement screen.getByText(Button clicked!); expect(messageElement).toBeInTheDocument(); }); // Cypress 测试示例 // cypress/e2e/app.cy.js describe(App, () { it(loads successfully, () { cy.visit(/); cy.contains(Learn React); }); it(handles button click, () { cy.visit(/); cy.get(button).click(); cy.contains(Button clicked!); }); });6. 持续集成和持续部署使用现代 CI/CD 工具提高部署效率。// GitHub Actions 配置 // .github/workflows/ci.yml name: CI on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Use Node.js uses: actions/setup-nodev3 with: node-version: 18 - run: npm ci - run: npm run lint - run: npm run test - run: npm run build // GitHub Actions 部署配置 // .github/workflows/deploy.yml name: Deploy on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Use Node.js uses: actions/setup-nodev3 with: node-version: 18 - run: npm ci - run: npm run build - name: Deploy to Vercel uses: amondnet/vercel-actionv20 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} working-directory: ./ // GitLab CI 配置 // .gitlab-ci.yml stages: - test - build - deploy test: stage: test script: - npm ci - npm run lint - npm run test build: stage: build script: - npm run build artifacts: paths: - dist deploy: stage: deploy script: - echo Deploying to production environment: name: production only: - main7. 容器化使用容器化技术提高部署一致性。// Dockerfile FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build EXPOSE 3000 CMD [npm, run, preview] // docker-compose.yml version: 3 services: frontend: build: . ports: - 3000:3000 environment: - NODE_ENVproduction restart: always // Kubernetes 配置 // frontend-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: frontend labels: app: frontend spec: replicas: 3 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: containers: - name: frontend image: frontend:latest ports: - containerPort: 3000 --- apiVersion: v1 kind: Service metadata: name: frontend spec: selector: app: frontend ports: - port: 80 targetPort: 3000 type: LoadBalancer8. 监控和日志使用现代监控和日志工具提高系统可靠性。// Sentry 配置 import * as Sentry from sentry/browser; import { Integrations } from sentry/tracing; Sentry.init({ dsn: your-dsn, integrations: [new Integrations.BrowserTracing()], tracesSampleRate: 1.0 }); // LogRocket 配置 import LogRocket from logrocket; import setupLogRocketReact from logrocket-react; LogRocket.init(your-app-id); setupLogRocketReact(LogRocket); // 自定义日志工具 // src/utils/logger.js const logger { info: (message, data) { console.log([INFO], message, data); // 发送到日志服务 }, warn: (message, data) { console.warn([WARN], message, data); // 发送到日志服务 }, error: (message, data) { console.error([ERROR], message, data); // 发送到日志服务 } }; export default logger; // 使用示例 import logger from ./utils/logger; logger.info(User logged in, { userId: 123 }); logger.warn(API request failed, { endpoint: /api/data }); logger.error(Authentication error, { error: Invalid token });9. 前端工程化最佳实践// 前端工程化最佳实践 // 1. 项目结构 // 合理的项目结构便于维护 // 2. 依赖管理 // 使用包管理器管理依赖定期更新 // 3. 代码规范 // 使用 ESLint、Prettier、TypeScript 等工具 // 4. 版本控制 // 使用 Git合理使用分支编写良好的 commit 信息 // 5. 自动化测试 // 编写单元测试、集成测试、端到端测试 // 6. CI/CD // 配置持续集成和持续部署 // 7. 容器化 // 使用 Docker 容器化应用 // 8. 监控和日志 // 配置监控和日志系统 // 9. 文档 // 编写清晰的文档 // 10. 团队协作 // 制定团队开发规范使用协作工具10. 前端工程化工具// 前端工程化工具 // 1. 构建工具 // Vite、esbuild、Rollup、Webpack // 2. 包管理器 // npm、yarn、pnpm // 3. 代码规范 // ESLint、Prettier、TypeScript // 4. 版本控制 // Git、GitHub、GitLab、Bitbucket // 5. 自动化测试 // Jest、Testing Library、Cypress // 6. CI/CD // GitHub Actions、GitLab CI、Jenkins、CircleCI // 7. 容器化 // Docker、Kubernetes // 8. 监控和日志 // Sentry、LogRocket、Datadog、New Relic // 9. 文档 // Storybook、Docusaurus、VuePress // 10. 协作工具 // Slack、Microsoft Teams、Jira、Trello前端工程化最佳实践1. 项目结构合理的目录结构按照功能或模块组织代码组件化将 UI 拆分为可复用的组件模块化将业务逻辑拆分为可复用的模块工具函数将通用功能封装为工具函数配置文件集中管理配置文件2. 依赖管理版本锁定使用 package-lock.json 或 yarn.lock 锁定依赖版本定期更新定期更新依赖修复安全漏洞依赖审查审查依赖项移除不必要的依赖私有包使用私有包管理内部共享代码依赖分析使用依赖分析工具分析依赖树3. 代码规范统一的代码风格使用 ESLint 和 Prettier 统一代码风格类型安全使用 TypeScript 提供类型安全代码质量使用静态代码分析工具检查代码质量代码审查进行代码审查确保代码质量文档注释为代码添加文档注释4. 版本控制分支策略使用 Git Flow 或 GitHub Flow 等分支策略Commit 规范使用 Conventional Commits 规范 commit 信息标签管理使用标签管理版本代码审查使用 Pull Request 或 Merge Request 进行代码审查CI/CD 集成与 CI/CD 工具集成5. 自动化测试测试覆盖率设置测试覆盖率目标单元测试测试单个组件或函数集成测试测试组件之间的交互端到端测试测试完整的用户流程测试环境在不同环境中测试6. CI/CD自动化构建每次提交自动构建自动化测试每次提交自动运行测试自动化部署合并到主分支自动部署环境管理管理多个环境开发、测试、生产回滚机制提供快速回滚能力7. 容器化一致的环境确保开发、测试、生产环境一致隔离性隔离应用避免依赖冲突可扩展性便于水平扩展部署速度提高部署速度资源利用提高资源利用率8. 监控和日志错误监控监控前端错误性能监控监控前端性能用户行为监控用户行为日志管理集中管理日志告警机制设置告警机制9. 文档项目文档编写项目说明文档API 文档编写 API 文档组件文档使用 Storybook 等工具编写组件文档开发指南编写开发指南部署指南编写部署指南10. 团队协作开发规范制定团队开发规范协作工具使用协作工具Slack、Jira 等代码审查进行代码审查知识共享共享知识和经验定期会议定期召开团队会议前端工程化案例1. 案例一大型电商网站某大型电商网站通过以下工程化措施提高了开发效率和代码质量现代构建工具使用 Vite 构建构建时间从 5 分钟减少到 30 秒代码规范使用 ESLint、Prettier、TypeScript代码错误率降低 80%自动化测试编写单元测试和端到端测试测试覆盖率达到 85%CI/CD配置 GitHub Actions实现自动构建、测试和部署容器化使用 Docker 容器化应用部署时间从 1 小时减少到 10 分钟2. 案例二企业内部系统某企业内部系统通过以下工程化措施提高了系统可靠性和可维护性项目结构采用模块化设计代码可维护性提高 60%依赖管理使用 pnpm 管理依赖依赖安装时间减少 70%监控和日志使用 Sentry 和 LogRocket错误响应时间从 24 小时减少到 1 小时文档使用 Storybook 编写组件文档新成员上手时间从 2 周减少到 3 天团队协作使用 Jira 管理任务开发效率提高 40%3. 案例三SaaS 产品某 SaaS 产品通过以下工程化措施提高了部署效率和用户体验CI/CD配置 GitLab CI实现自动部署到多个环境容器化使用 Kubernetes 管理容器系统可用性达到 99.99%监控和日志使用 Datadog 监控系统性能响应时间减少 50%前端性能使用 Vite 和代码分割页面加载时间减少 60%安全使用 Snyk 监控依赖项安全安全漏洞修复时间减少 80%总结前端工程化是现代前端开发的重要组成部分它可以提高开发效率、代码质量、团队协作能力、部署效率和可维护性。别再手动配置了现代构建工具、包管理器、代码规范工具、版本控制工具、自动化测试工具、CI/CD 工具、容器化技术、监控和日志工具等已经提供了更强大、更高效的工程化能力。记住前端工程化不仅仅是技术问题还包括团队协作、流程管理等多个方面。你需要综合考虑这些因素才能创建出高质量的前端应用。别再忽视前端工程化了它是前端开发的必备技能

相关文章:

前端工程化新方法:别再手动配置了

前端工程化新方法:别再手动配置了 什么是前端工程化新方法? 前端工程化新方法是指在前端开发中,随着技术的发展,出现的新的工程化技术和方法。别以为工程化只是配置 Webpack,那是十年前的玩法了。 为什么需要关注前端工…...

Qwen3.5-9B多模态能力展示:同一张产品图→识别品牌/描述功能/生成营销文案

Qwen3.5-9B多模态能力展示:同一张产品图→识别品牌/描述功能/生成营销文案 1. 多模态AI的惊艳表现 想象一下,当你上传一张产品图片,AI不仅能准确识别品牌和型号,还能详细描述产品功能,甚至为你生成吸引人的营销文案—…...

深度学习——交叉熵损失函数

调用示例 loss_fun F.cross_entropy()loss loss_fun(y_pred, labels)一句话描述 交叉熵损失函数是描述:预测的概率分布和真实概率分布之间差异的损失函数。差异越大,损失值越高;差异越小,损失值越低。 举例说明 假设有一只猫的图…...

解锁RK平台OpenCV+GStreamer全链路硬件加速:从解码到色彩转换的性能跃迁

1. 为什么你的RK平台视频处理帧率上不去? 第一次在RK3588上跑OpenCV视频处理时,我也被诡异的帧率数据惊到了——明明用了GStreamer硬解码,1080p视频居然只能跑到7帧!这就像买了辆跑车却只能龟速前进。经过反复测试发现&#xff0c…...

XUpdate自定义主题实战:打造独特版本更新提示界面

XUpdate自定义主题实战:打造独特版本更新提示界面 【免费下载链接】XUpdate 🚀A lightweight, high availability Android version update framework.(一个轻量级、高可用性的Android版本更新框架) 项目地址: https://gitcode.com/gh_mirrors/xu/XUpda…...

3DSident:你的任天堂3DS系统信息检测终极指南 [特殊字符]

3DSident:你的任天堂3DS系统信息检测终极指南 🎮 【免费下载链接】3DSident PSPident clone for 3DS 项目地址: https://gitcode.com/gh_mirrors/3d/3DSident 对于任天堂3DS的自制软件爱好者和技术用户来说,了解设备详细信息至关重要。…...

python mixer

## 聊聊 Python 里的 Mixer:一个不太起眼但很省事的工具 平时写代码,尤其是做测试或者快速搭建原型的时候,经常需要一堆假数据。比如用户的名字、邮箱、文章的标题和内容,或者订单的金额。自己手动编这些数据,写个循环…...

TCP 长连接服务:登录注册认证体系实战指南

TCP 长连接服务:登录注册认证体系实战指南 在 IM 即时通讯、游戏服务、物联网设备通信等 TCP 长连接场景中,连接准入认证是服务安全的第一道防线。 我们需要实现一套「先认证、后业务」的流程:客户端 TCP 连接建立后,不直接开放业…...

【TCP/IP】IIS FTP服务器端口冲突与匿名登录配置实战

1. IIS FTP服务器端口冲突问题解析 最近在搭建FTP服务器做TCP/IP协议分析实验时,遇到了一个典型问题:IIS FTP服务无法正常启动,匿名登录总是失败。经过排查发现,原来是FileZilla Server偷偷占用了21端口。这种情况在实际工作中很常…...

Simulink与Matlab协同建模仿真

Simulink 是 MATLAB 环境中的一个核心工具箱,构成了一个紧密集成的、以图形化建模和仿真为核心的动态系统分析平台。它们的关系与分工可以概括为:MATLAB 提供底层的计算引擎、编程语言和算法库,而 Simulink 则在此之上提供了一个直观的、基于…...

MQTT over WebSocket实战指南:从EMQX安装到消息收发全流程

1. MQTT over WebSocket 技术解析 MQTT over WebSocket 是物联网领域常用的通信方案,它巧妙地将MQTT协议的轻量级特性与WebSocket的浏览器友好性相结合。这种组合方式特别适合需要浏览器与物联网设备双向通信的场景,比如智能家居控制面板、工业监控大屏等…...

青少年软编等考五级题解目录

这个专栏发布中国电子学会主办的青少年软件编程等级考试 C 语言五级题目解析,每篇文章包含一次考试完整题目的思路解析。由于考级允许使用 C/C 语言,因此解析中给出的参考代码均为 C 代码。为了方便大家查找,特此发布一篇文章作为目录。 所有…...

Ubuntu20.04编译Carla0.9.13实战:从环境配置到资源下载的完整避坑指南

1. 环境准备:Ubuntu20.04基础配置 在开始编译Carla0.9.13之前,确保你的Ubuntu20.04系统已经完成基础环境配置。我实测发现,跳过这一步会导致后续编译过程中出现各种依赖缺失问题。首先打开终端,执行系统更新: sudo a…...

青少年软编等考四级题解目录

这个专栏发布中国电子学会主办的青少年软件编程等级考试 C 语言四级题目解析,每篇文章包含一次考试完整题目的思路解析。由于考级允许使用 C/C 语言,因此解析中给出的参考代码均为 C 代码。为了方便大家查找,特此发布一篇文章作为目录。 所有…...

从‘遍地都是’到‘最新版本’:聊聊H5st参数演变与前端风控对抗的那些事儿

H5st参数演进史:一场前端风控与自动化脚本的永恒博弈 当你在电商平台浏览商品时,页面背后正上演着一场看不见的攻防战。H5st参数作为这场战役中的关键武器,已经从最初的简单防御演变为如今复杂的加密体系。这串看似随机的字符,实际…...

小红书博主必看:AI智能体如何5分钟搞定高颜值封面+3张内容页(附保姆级教程)

小红书博主效率革命:AI智能体5分钟打造高颜值图文全攻略 每次打开小红书后台准备更新内容时,你是不是也经历过这样的纠结:花半小时找模板、一小时调排版,最后出来的效果还是不够"小红书"?作为深耕小红书运营…...

EVA-01部署教程:Qwen2.5-VL-7B模型微调+领域适配(NERV战术语料)

EVA-01部署教程:Qwen2.5-VL-7B模型微调领域适配(NERV战术语料) 1. 引言:欢迎来到NERV指挥中心 想象一下,你面前有一个能看懂图片、理解复杂场景、还能用“战术术语”和你对话的AI助手。它不仅能告诉你图片里有什么&a…...

CLIP ViT-H-14图像编码服务广告应用:创意海报图像情感倾向分析

CLIP ViT-H-14图像编码服务广告应用:创意海报图像情感倾向分析 1. 项目概述 CLIP ViT-H-14图像编码服务是基于CLIP ViT-H-14(laion2B-s32B-b79K)模型的图像特征提取解决方案,为开发者提供RESTful API和Web界面两种使用方式。这项服务特别适合需要分析图…...

达摩院春联模型实战教程:接入钉钉机器人实现群内春联点播

达摩院春联模型实战教程:接入钉钉机器人实现群内春联点播 过年贴春联,是咱们中国人的传统习俗。但每年想一副有新意、有文采的春联可不容易。现在好了,有了AI技术,这事儿变得简单又有趣。 今天要给大家分享的,就是如…...

Qwen3-ForcedAligner-0.6B多场景落地:无障碍服务为听障人士生成精准字幕流

Qwen3-ForcedAligner-0.6B多场景落地:无障碍服务为听障人士生成精准字幕流 1. 引言:让音频内容"看得见"的技术突破 想象一下这样的场景:一位听障朋友正在观看视频课程,虽然视频有字幕,但字幕与语音不同步&…...

从翻译到定制:手把手教你用Buildroot 2025.05手册玩转嵌入式Linux BSP开发

从翻译到实战:深度解析Buildroot 2025.05手册的嵌入式Linux开发实践 1. 嵌入式Linux开发的新范式 在嵌入式系统开发领域,Buildroot已成为构建轻量级Linux系统的首选工具之一。2025.05版本的Buildroot手册不仅是一份技术文档,更是嵌入式开发者…...

Linux系统下USB蓝牙SPP服务端开发实战:从环境配置到数据通信

1. 环境准备:从零搭建蓝牙开发环境 第一次在Linux下折腾蓝牙开发时,我对着满屏的命令行参数发懵。后来才发现,其实只要搞定三个核心组件就能开工:BlueZ蓝牙协议栈、USB蓝牙适配器驱动、基础开发工具链。这里分享下我验证过的配置方…...

【计算机网络】网络基础 (网络协议/TCP/IP协议栈/局域网内外数据传输/数据封装、解包、分用)

目录 计算机网络的发展历程 我国的互联网发展历程 认识“协议” 初识网络协议 OSI 七层模型 TCP/IP协议栈 TCP/IP协议栈、局域网、以太网、互联网之间的关系 局域网内部数据传输基本流程 数据的封装、解包和分用 以太网通信基本原理 跨局域网数据传输基本流程 计算机…...

STM32实战:串口USART数据收发与中断处理(基于STM32F103C8T6标准库)*从零到一*

1. 串口通信基础与STM32硬件准备 第一次接触STM32串口通信时,我对着USART和UART这两个词发懵——后来发现它们就像孪生兄弟,USART比UART多了同步时钟功能。我们常用的STM32F103C8T6开发板上有3个USART接口,最常用的是USART1,对应P…...

Ansible之Playbook(五):高级用法

Playbook高级用法一、本地执行(Local Action)应用场景当控制节点(非目标主机)需要执行特定操作时使用,如生成报告、处理临时文件等。OpenEuler实现方式- name: 在控制节点生成主机清单报告hosts: alltasks:- name: 收集…...

用于街头拍摄的摄像头

1 充电宝2 太阳能板我觉得用充电宝,物联网低功耗摄像头就可以了,因为录制的视频是等到拿回去以后再分析的,不用联网,联网是为了确保摄像头的安全,不被别人拿走。但是这个安装的过程:1 如果晚上12点去安装&a…...

未来5年最“钱“景岗位揭晓:AI产品经理,普通人如何从0到1逆袭?(内含3步进阶法+学习资源)

文章指出AI产品经理是未来5年最具潜力的岗位,并分析了想抓住AI机会的人常遇到的3种状态:观望者、探索者和跑偏者。文章将AI产品经理分为工具型、应用型和专业型,建议普通人以成为应用型AI产品经理为目标。文章提出了从入门到上手的3步学习法&…...

c++ string字符串详解

一.string背景以及需要了解的知识点 1.1STL string是STL的一部分,但是STL创建的比string晚一些,后面才把string加入到STL里。STL(standard template library)是c的重要组成部分,可以简单理解为一个囊括了数据结构里面我们学的结构与算法的集…...

AutoLisp实战:从零到一构建你的第一个绘图工具

1. 为什么选择AutoLisp来自动化绘图 如果你经常使用AutoCAD进行绘图工作,一定会遇到大量重复性的操作。比如每次都要手动选择两点画线,然后再单独添加标注。这种机械劳动不仅效率低下,还容易出错。AutoLisp就是AutoCAD内置的解决方案&#xf…...

Java-Study

基础环境搭建 下载jdk JDK 26 Documentation - Home JDK(Java Development Kit,Java 开发工具包) 是开发、编译、运行 Java 程序的核心基础环境,相当于你写 Java 代码的「工具箱 + 编译器 + 运行环境」三合一。 JDK 里到底有什么?(核心组成) JDK 不是一个单独的程序…...