JavaScript基础课程十九、前端工程化基础(npm + Vite)

本课作为前端开发的转型课,重点讲解npm依赖管理与Vite构建工具两大工程化基础。npm解决了第三方代码复用与依赖管理难题,让项目依赖可追溯、可快速恢复;Vite则简化了项目搭建与构建流程,极速的启动和热更新大幅提升开发效率,同时原生支持模块化与高级异步语法。工程化是现代前端开发的分水岭,告别原生手写代码的粗放模式,建立规范、高效、可维护的开发流程。掌握本课内容,不仅能独立搭建标准化前端项目,更是后续学习Vue、React等框架的必备前提,是前端从零基础迈向实战开发的关键一步。

一、课程学习目的

  1. 理解前端工程化的核心意义,告别原生手写代码的零散模式,建立规范化开发思维。

  2. 掌握npm包管理器的核心作用,熟练使用常用命令安装、管理、卸载第三方依赖。

  3. 理解package.json配置文件的作用,分清dependencies、devDependencies依赖区别。

  4. 掌握Vite快速搭建项目的流程,学会启动、打包项目,熟悉基础项目结构。

  5. 能够在工程化环境中运行模块化代码,为后续Vue/React框架学习奠定基础。

二、核心知识点讲解

1. 前端工程化概述

前端工程化是将零散的代码、资源、工具进行规范化、自动化、模块化管理的开发模式,解决传统开发中代码混乱、复用性差、依赖难管理、部署繁琐等问题,是现代前端开发的必备技能。

核心环节包含:依赖管理、模块化开发、项目构建、自动化部署、代码规范等,本课重点讲解npm依赖管理Vite项目构建两大基础工具。

2. npm 包管理器(Node Package Manager)

npm是Node.js自带的第三方包管理工具,用于下载、管理、共享前端代码库(依赖包),无需手动复制粘贴插件代码。

安装Node.js后会自动集成npm,通过终端命令即可操作,核心依托package.json文件记录项目信息与依赖清单。

3. npm 核心常用命令

  • npm -v:查看npm版本,验证是否安装成功

  • npm init:初始化项目,生成package.json配置文件

  • npm init -y:快速初始化,跳过问答环节

  • npm install 包名:安装指定依赖包(简写 npm i 包名)

  • npm install 包名 --save-dev:安装开发依赖(简写 npm i 包名 -D)

  • npm uninstall 包名:卸载指定依赖包

  • npm install:根据package.json安装所有依赖

4. Vite 构建工具基础

Vite是新一代前端构建工具,由Vue作者开发,主打极速启动、热更新、开箱即用,比WebPack更轻量高效,支持原生JS、Vue、React等多种项目。

Vite内置模块化支持,无需额外配置,可直接运行ES6模块化、async/await等高级语法,适合快速搭建工程化项目。

5. Vite 项目创建与运行流程

  1. 终端执行创建命令,选择项目模板(原生Vanilla/JS)

  2. 进入项目目录,安装依赖

  3. 启动开发服务器,实时预览项目

  4. 项目开发完毕,执行打包命令,生成上线文件

三、示例程序

示例1:npm初始化与安装依赖

bash 复制代码
# 1. 创建项目文件夹并进入
mkdir js-project && cd js-project

# 2. 快速初始化package.json
npm init -y

# 3. 安装常用工具包(如axios、dayjs)
npm i axios dayjs

# 4. 安装开发依赖(如vite)
npm i vite -D

示例2:Vite创建并启动项目

bash 复制代码
# 1. 创建Vite项目(选择Vanilla-原生JS)
npm create vite@latest

# 2. 按照提示操作
# 项目名称:js-vite-project
# 框架选择:Vanilla(原生JS)
# 语言选择:JavaScript

# 3. 进入项目目录
cd js-vite-project

# 4. 安装依赖
npm install

# 5. 启动开发服务器
npm run dev

# 6. 项目打包(上线用)
npm run build

示例3:工程化中使用模块化与异步代码

javascript 复制代码
// utils.js 模块文件(导出)
// 封装异步请求方法
export async function fetchData(url) {
  try {
    const res = await fetch(url);
    return await res.json();
  } catch (err) {
    console.error('请求失败', err);
    throw err;
  }
}

// main.js 主文件(导入使用)
import { fetchData } from './utils.js';

// 异步调用
async function init() {
  const data = await fetchData('./data/word.json');
  console.log('工程化异步数据:', data);
}

init();

四、掌握技巧与方法

  1. 项目必须先初始化npm(npm init -y),再安装依赖,保证依赖可追溯。

  2. 区分生产依赖(dependencies,项目运行必需)和开发依赖(devDependencies,仅开发用)。

  3. Vite项目启动后,复制终端地址到浏览器访问,修改代码会自动热更新。

  4. 模块化文件路径需正确,导入导出语法规范,避免路径报错。

  5. node_modules文件夹体积大,上传代码时无需提交,通过package.json即可恢复依赖。

  6. 遇到依赖安装失败,可删除node_modules和package-lock.json,重新执行npm install。

五、课后作业

基础作业

  1. 安装Node.js,验证npm、node版本,查看是否安装成功。

  2. 使用npm init初始化项目,安装axios、dayjs两个依赖包。

  3. 查看生成的package.json文件,找到dependencies依赖记录。

进阶作业

  1. 用Vite创建原生JS项目,启动并访问默认页面,测试热更新效果。

  2. 在Vite项目中拆分两个模块,实现ES6导出导入,运行无报错。

  3. 执行npm run build打包项目,查看生成的dist打包目录。

实战作业

  1. 在Vite工程化项目中,整合async/await异步请求、模块化拆分,实现单词数据异步加载、页面渲染功能,完成完整工程化实战。

上一课:异步编程高级(async/await + 模块化)实战作业代码

代码功能说明

本实战代码紧扣async/await与ES6模块化核心考点,采用英语单词加载场景,实现模块化拆分与异步逻辑全流程。代码拆分为数据模块、工具模块、主逻辑模块,通过export/import完成导入导出;封装异步请求函数,依托async/await实现同步风格的异步串行、并行加载,搭配try/catch捕获异常;页面实现加载提示、成功渲染、错误兜底交互,直观展示模块化解耦、async/await语法、异常处理、Promise.all并行等核心知识点,可直接在浏览器运行,贴合课程考点,为工程化学习铺垫基础。

注意事项

  • 浏览器运行模块化代码,script标签必须添加 type="module" 属性,否则会报错。

  • await关键字只能在async修饰的函数内部使用,禁止在全局或普通函数中单独调用。

  • 所有async/await逻辑必须包裹try/catch,规范捕获异步异常,防止程序中断。

  • 模块化导入路径需写完整相对路径,文件名、后缀名不可省略,避免路径错误。

  • 无依赖的异步任务,用Promise.all+await实现并行执行,提升加载效率。

  • async函数默认返回Promise对象,可继续链式调用,但推荐用try/catch简化写法。

  • 运行代码时打开浏览器控制台,排查模块化、异步语法相关报错,加深理解。

完整实战代码

代码结构(单HTML整合版,无需多文件,直接运行)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>第16课 async/await+模块化实战</title>
    <style>
        .box {
            width: 750px;
            margin: 50px auto;
            padding: 30px;
            border: 1px solid #eee;
            border-radius: 10px;
            font-family: "Microsoft YaHei";
            box-shadow: 0 0 12px rgba(0,0,0,0.06);
        }
        .btn {
            padding: 10px 20px;
            margin: 10px 8px;
            background: #42b983;
            color: #fff;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            transition: 0.3s;
        }
        .btn:hover {
            background: #359469;
        }
        .result {
            margin-top: 25px;
            padding: 20px;
            line-height: 2;
            border-top: 1px dashed #eee;
            min-height: 180px;
        }
        .item {
            margin: 8px 0;
            padding: 10px;
            background: #f9f9f9;
            border-radius: 5px;
        }
        .loading { color: #666; }
        .error { color: #f56c6c; }
    </style>
</head>
<body>
    <div class="box">
        <h2>async/await 单词模块化加载器</h2>
        <button class="btn" onclick="serialLoad()">串行加载单词</button>
        <button class="btn" onclick="parallelLoad()">并行加载单词</button>
        <button class="btn" onclick="clearResult()">清空结果</button>
        <div class="result" id="result"></div>
    </div>

    <!-- 模块化核心:type="module" -->
    <script type="module">
        const resDom = document.getElementById("result");
        // 渲染工具函数
        function render(html, className = '') {
            resDom.innerHTML += `<div class="item ${className}">${html}</div>`;
        }
        // 清空结果
        window.clearResult = () => resDom.innerHTML = "";

        // ==================== 模块1:异步数据模块(模拟导出)====================
        function mockFetchWord(word) {
            return new Promise((resolve, reject) => {
                render(`加载中:${word}`, "loading");
                setTimeout(() => {
                    if (word) resolve({ en: word, cn: "中文释义", status: "success" });
                    else reject("单词参数无效");
                }, 1200);
            });
        }

        // 导出异步方法
        export async function getSingleWord(word) {
            try {
                return await mockFetchWord(word);
            } catch (err) {
                throw err;
            }
        }

        export async function getBatchWord(words) {
            try {
                return await Promise.all(words.map(item => mockFetchWord(item)));
            } catch (err) {
                throw err;
            }
        }

        // ==================== 主逻辑:导入并使用模块====================
        import { getSingleWord, getBatchWord } from './#mock-module.js';

        // 串行加载(绑定全局,供按钮调用)
        window.serialLoad = async function () {
            try {
                const res1 = await getSingleWord("apple");
                render(`成功:${res1.en} - ${res1.cn}`);
                const res2 = await getSingleWord("banana");
                render(`成功:${res2.en} - ${res2.cn}`);
            } catch (err) {
                render(`错误:${err}`, "error");
            }
        };

        // 并行加载(绑定全局,供按钮调用)
        window.parallelLoad = async function () {
            try {
                const results = await getBatchWord(["apple", "banana", "orange"]);
                results.forEach(item => {
                    render(`批量成功:${item.en} - ${item.cn}`);
                });
            } catch (err) {
                render(`错误:${err}`, "error");
            }
        };
    </script>
</body>
</html>

作业验收标准

  1. 页面按钮点击正常,模块化语法无报错,async/await执行顺畅。

  2. 串行加载按顺序执行,并行加载同步执行,效率差异直观。

  3. try/catch异常捕获到位,错误提示友好,加载状态清晰。

  4. 代码模块化拆分规范,导出导入语法正确,贴合第16课核心考点。

相关推荐
全栈前端老曹2 个月前
【包管理】read-pkg-up 快速上手教程 - 读取最近的 package.json 文件
前端·javascript·npm·node.js·json·nrm·package.json
big tail10 个月前
项目依赖版本修改
npm·pnpm·react·yarn·依赖·package.json
高端客户1 年前
package,json 文件中依赖包的说明
npm·file·link·package.json·本地依赖包·版本标识符
wlym1231 年前
npm 中的 package.json 实践
前端·npm·package.json
wlym1231 年前
npm-run-all 使用实践
前端·npm·package.json
仙魁XAN2 年前
Unity 功能 之 创建 【Unity Package】 Manager 自己自定义管理的包的简单整理
unity·游戏引擎·ump·package.json·unitypackage
呀呀夫斯基2 年前
从零开始的<vue2项目脚手架>搭建:vite+vue2+eslint
package.json·npm init
Vinkan@2 年前
初识 peerDependencies
前端·npm·vue·vue-router·package.json
赢乐2 年前
从零开始:构建、打包并上传个人前端组件库至私有npm仓库的完整指南
打包·构建·package.json·publish·私有npm仓库·前端组件库·组件代码