关于nest项目打包

最近在用nest做一些工具,开发阶段挺好用,等到打包时遇到了各种各样的问题,在这里简单总结下。

一、nest build

如果使用nest build进行打包,你将会得到一份和原目录相同的目录结构输出。

为什么?

因为NestJS CLI仅做如下处理:

  1. 读取配置文件:读取nest-cli.json等配置文件,确定构建选项和输出目录。
  2. TypeScript编译
  3. 部分文件处理:复制静态资源,处理路径映射
  4. 优化操作:代码压缩 以及生成source map

可以看到,NestJS CLI 并没有像webpack一样,将不同文件打包成一个,而是保留了原有目录结构。

二、关于.map文件

上面我们提到,会生成.map文件。有些同学可能会有疑问,.map 不是在浏览器中使用的么?服务端项目为什么还需要.map文件?这就要讲到.map文件的使用场景:

  1. 错误调试与堆栈跟踪

    当服务端运行时出现错误,Node.js会生成错误堆栈信息。如果没有Source map,错误信息会指向编译后的JavaScript代码的行号,而不是原始的TypeScript代码。这使得定位和修复问题变得非常困难。

  2. 性能分析

在进行性能分析时,source map可以帮助开发者识别哪些原始TypeScript代码段在运行时消耗了最多资源。这对于优化关键路径和提高应用性能至关重要。

  1. 开发体验优化

在开发环境中,使用source map可以获得更好的开发体验。例如,当使用Node.js的调试器或日志记录时,可以直接看到和引用原始的TypeScript代码,而不是编译后的JavaScript代码。

  1. 日志记录增强

在日志系统中,可以通过source map将日志中记录的代码位置转换回原始TypeScript文件位置,使日志信息更有意义和可操作。

三、为什么不将依赖包打包进最终结果中?

nest项目打包,建议采用分离依赖的方式,即打包后单独安装依赖。

优势:

  1. 镜像体积更小(如果采用docker方式的话):只包含编译后的代码

  2. 缓存友好:Docker构建时可以分层缓存

  3. 部署灵活:可以在目标环境安装特定版本的依赖

  4. 标准实践:符合Node.js生态的常见做法

    为什么不推荐打包依赖进dist?

  5. 体积臃肿:node_modules会非常大

  6. 路径问题:可能出现模块解析错误

  7. 平台兼容性:native依赖可能不兼容目标平台

webpack打包示例:

js 复制代码
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: './src/main.ts',// 入口问啊进
  target: 'node',
  mode: process.env.NODE_ENV || 'production',
  output: {
    path: path.resolve(__dirname, 'dist'), //输出目录
    filename: 'bundle.js',// 输出结果
  },
  resolve: {
    extensions: ['.ts', '.js'],// 支持的文件扩展名
    plugins: [
      new TsconfigPathsPlugin({// 支持tsconfig路径映射
        configFile: './tsconfig.json',
      }),
    ],
  },
  module: {
    rules: [
      {
        test: /\.ts$/, // 处理TypeScript文件
        use: {
          loader: 'ts-loader',  
          options: {
            transpileOnly: true, // 只编译,不做类型检查
          },
        },
        exclude: /node_modules/, //排除 node_modules
      },
    ],
  },
  externals: [nodeExternals()],  // 排除所有 node_modules 依赖;不打包 [node_modules](),运行时从外部加载,这就是为什么你需要在部署环境安装依赖的原因
  plugins: [
    new CleanWebpackPlugin(), // 清理dist目录
    new ForkTsCheckerWebpackPlugin(),// 在单独进程中进行类型检查
    new CopyPlugin({ //将静态文件复制到dist目录
      patterns: [
        {
          from: path.resolve(__dirname, 'public'),
          to: path.resolve(__dirname, 'dist/public'),
        },
        {
          from: path.resolve(__dirname, 'package.json'),
          to: path.resolve(__dirname, 'dist/package.json'),
        },
        {
          from: path.resolve(__dirname, '.env'),
          to: path.resolve(__dirname, 'dist'),
        },
      ],
    }),
  ],
  optimization: {
    minimize: process.env.NODE_ENV === 'production',
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: process.env.NODE_ENV === 'production',// 生产环境移除 console
          },
        },
      }),
    ],
  },
  devtool: process.env.NODE_ENV === 'production' ? 'source-map' : 'eval-cheap-module-source-map',
};

四、为什么静态文件没有打包到最终的boundle.js中

  1. 在Node.js应用中,静态文件和配置文件通常保持独立,便于在运行时直接读取或修改,而不是打包进最终结果中
  2. webpack默认只会打包通过import或require引入的JavaScript/TypeScript模块。
  3. .env问啊进包含环境变量,通常需要在运行时读取,保持其独立文件形式更灵活;public目录下的文件通常是静态资源,需要通过路径访问。
  4. 如果需要使用,可以在webpack打包时,将.env文件等复制到dist目录下。

五、fetch api

如果你在代码中使用了fetch api,开发环境没有问题,但是打包后将报错fetch is not defined。因为Node18以下版本中,默认不包含浏览器的原生fetch API,如需使用,需要引入node-fetch。18以上就可以正常使用了。

相关推荐
fdc20177 小时前
Avalonia:使用附加属性实现命令与事件的绑定
javascript·windows·microsoft
Mike_jia8 小时前
uuWAF:开源Web应用防火墙新标杆——从工业级防护到智能防御实战解析
前端
掘金安东尼8 小时前
Chrome 17 岁了——我们的浏览器简史
前端·javascript·github
袁煦丞8 小时前
群晖NAS FTP远程文件仓库全球访问:cpolar内网穿透实验室第524个成功挑战
前端·程序员·远程工作
前端小巷子8 小时前
JS 打造动态表格
前端·javascript·面试
excel8 小时前
从卷积到全连接:用示例理解 CNN 的分层
前端
UNbuff_08 小时前
HTML 各种事件的使用说明书
前端·html
Mr. Cao code8 小时前
探索OpenResty:高性能Web开发利器
linux·运维·服务器·前端·nginx·ubuntu·openresty
li357416 小时前
将已有 Vue 项目通过 Electron 打包为桌面客户端的完整步骤
前端·vue.js·electron