查看: 121|回复: 1

Node.js 模块化与 Webpack 工程化入门实践:从 CommonJS 到打包配置详解

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
对于前端开发者来说,Node.js 已经不仅是服务端语言,更是工程化工具的基石。本文从 Node.js 内置模块入手,贯通模块化标准、npm 包管理,最终落地到 Webpack 打包配置,帮助初学者建立完整的知识链路。

## 1. Node.js 基础:文件操作与路径安全

Node.js 基于 Chrome V8 引擎,让 JavaScript 脱离浏览器运行。执行脚本只需在终端运行 `node 文件名.js`。

### fs 模块:读写文件

`fs` 是 Node.js 内置的文件系统模块。写入文件使用 `fs.writeFile(path, data, callback)`,读取文件使用 `fs.readFile(path, callback)`,读取到的 `data` 是 Buffer 对象,需调用 `.toString()` 转换为字符串。
  1. const fs = require('fs');
  2. // 写入
  3. fs.writeFile('./test.txt', 'Hello FS', (err) => {
  4.   if (err) console.log(err);
  5.   else console.log('写入成功');
  6. });
  7. // 读取
  8. fs.readFile('./test.txt', (err, data) => {
  9.   if (err) console.log(err);
  10.   else console.log(data.toString()); // Hello FS
  11. });
复制代码

### path 模块:解决相对路径陷阱

Node.js 中相对路径是相对于终端工作目录,而非脚本文件所在目录。不同位置执行脚本可能导致路径找不到。安全做法是使用 `__dirname`(当前文件所在目录的绝对路径)配合 `path.join()` 拼接路径。
  1. const fs = require('fs');
  2. const path = require('path');
  3. const filePath = path.join(__dirname, '..', 'data.txt');
  4. fs.readFile(filePath, (err, data) => {
  5.   if (err) console.log(err);
  6.   else console.log(data.toString());
  7. });
复制代码

`path.join()` 会自动根据操作系统规则拼接路径片段。

### 实战:压缩 HTML 文件

前端工程化中常见的一步是压缩 HTML,去除回车和换行符。
  1. const fs = require('fs');
  2. const path = require('path');
  3. fs.readFile(path.join(__dirname, 'public', 'index.html'), (err, data) => {
  4.   const htmlStr = data.toString();
  5.   const resultStr = htmlStr.replace(/[\r\n]/g, '');
  6.   fs.writeFile(path.join(__dirname, 'dist', 'index.html'), resultStr, err => {
  7.     if (err) console.log(err);
  8.     else console.log('HTML压缩成功!');
  9.   });
  10. });
复制代码

### http 模块:搭建简易 Web 服务

使用内置 `http` 模块创建服务器,监听端口并返回响应。
  1. const http = require('http');
  2. const server = http.createServer();
  3. server.on('request', (req, res) => {
  4.   res.setHeader('Content-Type', 'text/plain;charset=utf-8');
  5.   res.end('欢迎使用 Node.js 创建的 Web 服务');
  6. });
  7. server.listen(3000, () => {
  8.   console.log('Web 服务已在 http://localhost:3000 启动');
  9. });
复制代码

根据请求路径返回不同文件(如 HTML):
  1. server.on('request', (req, res) => {
  2.   if (req.url === '/index.html') {
  3.     fs.readFile(path.join(__dirname, 'dist/index.html'), (err, data) => {
  4.       res.setHeader('Content-Type', 'text/html;charset=utf-8');
  5.       res.end(data.toString());
  6.     });
  7.   } else {
  8.     res.setHeader('Content-Type', 'text/html;charset=utf-8');
  9.     res.end('404 页面不存在');
  10.   }
  11. });
复制代码

## 2. 模块化开发:CommonJS 与 ES Modules

Node.js 中每个 `.js` 文件都是一个独立模块,变量作用域隔离。模块化带来代码复用、按需加载、便于协作。

### CommonJS 标准(Node.js 默认)

导出使用 `module.exports`,导入使用 `require()`。
  1. // utils.js
  2. const baseUrl = 'http://api.example.com';
  3. const sumArray = arr => arr.reduce((s, v) => s + v, 0);
  4. module.exports = {
  5.   url: baseUrl,
  6.   sum: sumArray
  7. };
  8. // index.js
  9. const utils = require('./utils.js');
  10. console.log(utils.url); // http://api.example.com
  11. console.log(utils.sum([1,2,3])); // 6
复制代码

内置模块直接写名字(如 `require('fs')`),自定义模块写路径(如 `require('./utils.js')`)。

### ES Modules(ECMAScript 标准)

在 `package.json` 中设置 `"type": "module"` 即可启用 ESM 语法。

**默认导出/导入**:
  1. // utils.js
  2. const baseUrl = 'http://api.example.com';
  3. export default { url: baseUrl };
  4. // index.js
  5. import utils from './utils.js';
  6. console.log(utils.url);
复制代码

**命名导出/导入**(按需加载):
  1. // utils.js
  2. export const baseUrl = 'http://api.example.com';
  3. export const sumArray = arr => arr.reduce((s, v) => s + v, 0);
  4. // index.js
  5. import { baseUrl, sumArray } from './utils.js';
  6. console.log(baseUrl, sumArray([1,2,3]));
复制代码

选择策略:全部加载用默认导出,按需加载用命名导出。

## 3. npm 包管理

包(Package)是包含 `package.json` 的文件夹,分为项目包和软件包。`package.json` 记录名称、版本、入口文件(`main` 字段)。

常用命令:
- `npm init -y`:快速生成 `package.json`
- `npm i <包名>`:安装本地依赖,记录到 `dependencies`
- `npm i <包名> -g`:全局安装(如 `nodemon`)
- `npm i`:根据 `package.json` 安装所有依赖

**nodemon 全局包**:监听文件变化自动重启应用,替代 `node` 命令。使用 `nodemon app.js` 启动。

## 4. Webpack 模块打包工具

Webpack 从入口出发构建依赖图,将 JS、CSS、图片等打包成静态资源。核心能力:转译、压缩、整合。

### 基础使用

初始化项目并安装:
  1. npm init -y
  2. npm i webpack webpack-cli --save-dev
复制代码

在 `package.json` 的 `scripts` 中添加命令:
  1. "scripts": {
  2.   "build": "webpack"
  3. }
复制代码

运行 `npm run build`,默认入口为 `src/index.js`,输出到 `dist/main.js`。

### 核心配置文件 webpack.config.js

通过配置文件自定义打包行为。
  1. const path = require('path');
  2. const HtmlWebpackPlugin = require('html-webpack-plugin');
  3. module.exports = {
  4.   // 打包模式:development 或 production
  5.   mode: 'development',
  6.   // 入口
  7.   entry: path.resolve(__dirname, 'src/login/index.js'),
  8.   // 出口
  9.   output: {
  10.     path: path.resolve(__dirname, 'dist'),
  11.     filename: './login/index.js'
  12.   },
  13.   // 插件
  14.   plugins: [
  15.     new HtmlWebpackPlugin({
  16.       template: './public/login.html',
  17.       filename: './login/index.html'
  18.     })
  19.   ],
  20.   // 加载器
  21.   module: {
  22.     rules: [
  23.       {
  24.         test: /\.css$/i,
  25.         use: ['style-loader', 'css-loader'] // 从右向左执行
  26.       },
  27.       {
  28.         test: /\.less$/i,
  29.         use: ['style-loader', 'css-loader', 'less-loader']
  30.       },
  31.       {
  32.         test: /\.(png|jpg|jpeg|gif)$/i,
  33.         type: 'asset',
  34.         generator: {
  35.           filename: 'assets/[hash][ext]'
  36.         }
  37.       }
  38.     ]
  39.   },
  40.   // 路径别名
  41.   resolve: {
  42.     alias: {
  43.       '@': path.resolve(__dirname, 'src')
  44.     }
  45.   },
  46.   // 开发服务器
  47.   devServer: {
  48.     port: 8080,
  49.     open: true,
  50.     hot: true
  51.   }
  52. };
复制代码

常用加载器说明:
- `css-loader`:解析 `@import` 和 `url()`
- `style-loader`:将 CSS 插入 DOM 的 `<style>` 标签
- `less-loader`:将 Less 编译为 CSS

安装命令:
  1. npm i html-webpack-plugin css-loader style-loader less less-loader mini-css-extract-plugin css-minimizer-webpack-plugin --save-dev
复制代码

### 常用优化配置

- **提取 CSS 为独立文件**:用 `mini-css-extract-plugin` 替代 `style-loader`,利于浏览器缓存
- **压缩 CSS**:使用 `css-minimizer-webpack-plugin`
- **Source Map**:设置 `devtool: 'inline-source-map'` 精确定位源码错误
- **CDN 排除**:通过 `externals` 配置将某些库排除打包,在 HTML 中引入 CDN 链接
- **代码分割**:在 `optimization.splitChunks` 中配置公共代码提取

### 打包模式与环境变量

`mode` 决定内置优化:`development` 启用调试和热更新,`production` 自动压缩。命令行可覆盖:`webpack --mode=production`。

通过 `cross-env` 注入环境变量:
  1. npm i cross-env --save-dev
复制代码

修改 `package.json`:
  1. "scripts": {
  2.   "build": "cross-env NODE_ENV=production webpack",
  3.   "dev": "cross-env NODE_ENV=development webpack serve"
  4. }
复制代码

在 `webpack.config.js` 中通过 `process.env.NODE_ENV` 判断环境,用 `DefinePlugin` 将变量注入前端代码。

多页面打包只需配置多个 `entry` 和对应的 `HtmlWebpackPlugin` 实例。

## 总结

从 Node.js 文件操作、路径安全,到模块化标准、npm 包管理,再到 Webpack 全配置,本文覆盖了从前端工程化入门所需的核心知识点。掌握这些,你就能自主搭建项目构建流程,实现模块化开发和优化。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Node.js 模块化与 Webpack 工程化入门实践:从 CommonJS 到打包配置详解

这篇入门文章写得非常清晰实用,把 Node.js 内置模块、模块化标准和工程化实践串成了一条完整的学习线。特别是对 `__dirname` 和 `path.join()` 的强调,确实能帮新手避开常见的路径陷阱。压缩 HTML 和搭建简易 Web 服务的例子也很有实战感,看完就能立刻上手尝试。不过标题里提到了 Webpack 打包配置,正文好像只讲到模块化部分就结束了,是后面还有内容没贴完吗?期待 Webpack 的工程化部分也能这样一步步拆解出来,对新手会更有帮助。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-13 11:02 , Processed in 0.027211 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部