# Next.js build को obfuscate करें

@afterpack/next client JavaScript को next build के अंदर obfuscate करता है, Turbopack या webpack पर, SSR या static export में।

Source: https://www.afterpack.dev/hi/docs/frameworks/nextjs

`@afterpack/next` आपके client JavaScript को `next build` के अंदर से obfuscate करता है। `withAfterpack` एक config लौटाता है जिसमें `compiler.runAfterProductionCompile` होता है, Next का अपना build hook, जिसे Next दोनों में से किसी भी bundler के लिए एक बार call करता है।

आपके config को wrap करना ही पूरा integration है। कोई lifecycle script नहीं, कोई अलग command नहीं।

## Install

```bash
npm install -D @afterpack/next
```

```ts
// next.config.ts
import type { NextConfig } from "next";
import { withAfterpack } from "@afterpack/next";

const nextConfig: NextConfig = {
  // your existing config
};

export default withAfterpack(nextConfig);
```

Next config का function रूप भी उसी तरह काम करता है। `withAfterpack(async (phase, ctx) => ({ … }))` एक wrapped function लौटाता है।

## Build

अब `next build` obfuscated output emit करता है, चाहे `.next/` किसी भी bundler (Turbopack या webpack) ने बनाया हो। `next dev` अछूता रहता है। `next build` का हर invocation hook चलाता है, उसे सीधे call करने वाला CI job भी, और कोई lifecycle script नहीं है जिसे कोई install छोड़ सके। Hook throw करे तो build exit code 1 के साथ fail हो जाती है।

Hook केवल client को serve होने वाला JavaScript obfuscate करता है: `.next/static/chunks`, और static export के लिए `out/` भी। `.next/server` कभी browser तक नहीं पहुँचता और obfuscate नहीं किया जाता। Hook हर content-hashed chunk का नाम बदलता है ताकि उसका नाम [उसके obfuscated bytes के साथ चले](https://www.afterpack.dev/hi/docs/builds#file-names-and-caching), और उसके references को फिर से लिखता है। Hook compilation के बाद और prerendering व static export से पहले चलता है, इसलिए static export obfuscated chunks को `out/` में copy करता है।

Hook चलने से पहले Next chunks लिख देता है, इसलिए build के दौरान लगभग एक सेकंड तक आपके unobfuscated chunks disk पर रहते हैं, और उस दौरान `.next/` पढ़ सकने वाली कोई भी चीज़ उन्हें पढ़ सकती है। In-pipeline plugins ([Vite](https://www.afterpack.dev/hi/docs/frameworks/vite), [Rollup](https://www.afterpack.dev/hi/docs/frameworks/rollup), [webpack](https://www.afterpack.dev/hi/docs/frameworks/webpack), [Parcel](https://www.afterpack.dev/hi/docs/frameworks/parcel)) इसके बजाय obfuscated bundle bundler को वापस सौंपते हैं, इसलिए unobfuscated कुछ भी कभी लिखा ही नहीं जाता।

अगर आपने पहले से `compiler.runAfterProductionCompile` hook सेट किया है, तो उसे replace नहीं किया जाता बल्कि उसके साथ जोड़ा जाता है। आपका पहले चलता है, AfterPack का दूसरे नंबर पर, इसलिए आपके hook को वही bytes दिखते हैं जो AfterPack install न होने पर दिखते।

`withAfterpack` को pass किए गए options hook के अंदर बंद रहते हैं। उनकी प्राथमिकता `AFTERPACK_*` environment variables से ऊपर है, जिनकी प्राथमिकता `afterpack.json` से ऊपर है। किसी फ़ाइल को अछूता छोड़ने के लिए [`paths.exclude`](https://www.afterpack.dev/hi/docs/config#paths-exclude) इस्तेमाल करें।

Map चालू होने पर संयुक्त [`protectionMap.html`](https://www.afterpack.dev/hi/docs/protection-map) आपके project root पर gitignored `.afterpack/` में लिखा जाता है। यह डिफ़ॉल्ट रूप से बंद है; देखें [Verify](#verify)।

## Verify

हर protected build आपके [project root](https://www.afterpack.dev/hi/docs/cli#files) में, `.next/` के बाहर, `.afterpack/receipts/.next.json` में एक receipt लिखती है: engine version, seed, bundler, build id, और हर obfuscated फ़ाइल का एक sha256। अपने deploy चरण में इसे assert करें:

```bash
npx afterpack@latest verify .
```

यह non-zero के साथ exit करता है जब receipt गायब हो, जब वह किसी दूसरी build की हो, या जब कोई दर्ज फ़ाइल अब उस value पर hash न हो जिस पर उसे obfuscate किया गया था।

static export का `out/` इन chunks की copy है, इसलिए `npx afterpack@latest verify out` उसे उसी receipt से जाँचता है और बदली गई हर फ़ाइल का नाम बताता है।

[Protection Map](https://www.afterpack.dev/hi/docs/protection-map) डिफ़ॉल्ट रूप से केवल तब लिखा जाता है जब bundler ने source map emit किया हो और build CI (`CI=true` या `CI=1`) में न चल रही हो। जब तक `productionBrowserSourceMaps` चालू न हो, Next.js कोई browser source maps emit नहीं करता, इसलिए map डिफ़ॉल्ट रूप से बंद रहता है। Local पर पूरे artifacts देखने के लिए स्पष्ट रूप से opt in करें:

```ts
export default withAfterpack(nextConfig, { protectionMap: { enabled: true } });
```

रिपोर्ट gitignored `.afterpack/protectionMap.html` में जाती है। इसमें आपका पूरा source होता है। इसे कभी commit या serve न करें।

> **Source maps को कभी production में ship न करें**
>
> एक `.map` फ़ाइल में आपका मूल source होता है। `productionBrowserSourceMaps: true` केवल तब सेट करें जब आप चाहते हैं कि Protection Map मूल source दिखाए। Hook served tree से maps हटा देता है और production में `//# sourceMappingURL` comment बंद रखता है।

## Options

हर [configuration key](https://www.afterpack.dev/hi/docs/config) `withAfterpack` के दूसरे argument के रूप में pass की जा सकती है, उदाहरण के लिए `withAfterpack(nextConfig, { preset: "hard", complexity: 40 })`।

## Directives

Directives एक [Pro](https://www.afterpack.dev/hi/docs/pro) feature हैं। [Free build](https://www.afterpack.dev/hi/docs/directives#free-builds) में protection बढ़ाने वाला directive build को `DIAG_PRO_DIRECTIVE_REQUIRES_KEY` के साथ रोक देता है।

Directives को plugin आपके source से पढ़ता है, और built chunks में उनकी जगह खोजने के लिए `productionBrowserSourceMaps: true` चाहिए। देखें [Directives](https://www.afterpack.dev/hi/docs/directives)।

## Edge cases

- **`experimental.sri` अस्वीकार है।** Next हर asset का integrity hash उसे लिखते समय ही compute करता है, किसी भी build hook के चलने से पहले, इसलिए बाद में दोबारा लिखे गए chunk को browser block कर देता है। `experimental.sri` हटाएँ, या `withAfterpack` हटाएँ।
- **स्थिर `generateBuildId` बदली हुई फ़ाइलों को एक ही URL पर रखता है।** अगर build id releases के बीच वही रहता है, तो `static/<buildId>/_buildManifest.js` और `_ssgManifest.js` अपना URL बनाए रखते हैं जबकि उनके bytes बदल जाते हैं, और build चेतावनी देता है। `generateBuildId` को unset छोड़ें ताकि Next हर build के लिए random id चुने, या हर release में नया id लौटाएँ।
- **`.next/` पर point करें, `dist/` पर नहीं।** अगर आप इस package के बजाय [generic CLI](https://www.afterpack.dev/hi/docs/cli#usage) इस्तेमाल करते हैं, तो `npx afterpack@latest .next/static/chunks` समकक्ष target है, लेकिन यह served maps आपके लिए नहीं हटाता।
- **Unobfuscated फ़ाइलों पर [fail-closed](https://www.afterpack.dev/hi/docs/diagnostics#fail-closed-no-exceptions), बिना किसी override के।** अगर engine किसी फ़ाइल को सुरक्षित रूप से obfuscate नहीं कर सकता, तो build fail हो जाती है और उस फ़ाइल का नाम बताती है। अगर किसी फ़ाइल को कभी obfuscate नहीं होना चाहिए, तो उसे [`paths.exclude`](https://www.afterpack.dev/hi/docs/config#paths-exclude) से pass से पूरी तरह बाहर रखें।

## आगे

- [Frameworks](https://www.afterpack.dev/hi/docs/frameworks): पूरी matrix।
- [Quickstart](https://www.afterpack.dev/hi/docs/quickstart): install, build और verify।
- [Builds & CI](https://www.afterpack.dev/hi/docs/builds): seeds, dev-बनाम-prod, वही bytes promote करना।
- [Protection Map](https://www.afterpack.dev/hi/docs/protection-map): रिपोर्ट पढ़ना।
- [Directives](https://www.afterpack.dev/hi/docs/directives): हर marker key, और वह क्या करती है।
- [Configuration](https://www.afterpack.dev/hi/docs/config): engine की config surface।
