parcel-bundler / parcel

The zero configuration build tool for the web. πŸ“¦πŸš€
https://parceljs.org
MIT License
43.5k stars 2.27k forks source link

Namer Plugins - Separate naming process from on-disk file path #9982

Open sdedovic opened 1 month ago

sdedovic commented 1 month ago

I have searched the issues / PRs and cannot find something to help support what I need. I am happy to open a PR if someone can point me in the correct direction.

πŸ™‹ feature request

I want to be able to split my assets up by type into two separate folders, without the Namer changing paths.

dist
β”œβ”€β”€ static
β”‚Β Β  β”œβ”€β”€ assets
β”‚Β Β  β”‚Β Β  └── hammer-icon.svg
β”‚Β Β  β”œβ”€β”€ index.61d3354a.css
β”‚Β Β  β”œβ”€β”€ index.61d3354a.css.map
β”‚Β Β  β”œβ”€β”€ index.b71e74eb.js
β”‚Β Β  └── index.b71e74eb.js.map
└── template
    β”œβ”€β”€ base.htpp
    └── index.htpp

This is because files under template will be deployed to a server application and files under static will be deployed to a CDN.

Another way to view this - after the Namer, Optimizesr, Compressors run, partition the files into two folders based on bundle type without changing the name.

πŸ€” Expected Behavior

Naming assets (in a Namer plugin) is separate from placing them in the output directory (e.g. support a subdir without changing all the paths).

😯 Current Behavior

The name is the path on disk and the reference in other assets (e.g. src="...")

πŸ’ Possible Solution

As far as I am aware, this cannot be done now. I was thinking of changing the Namer contract to return either a FilePath string or an object of the structure:

interface NamerReturn {
  name: string;
  subdirectory: FIlePath;
}

To support existing behviour (where these are the same) and new behaviour (where these can be different).

πŸ”¦ Context

I am using Parcel to develop HTML templates. The template files I write reference JS, CSS, and other types of assets relatively. Parcel then processes these Templates to resolve references to assets and point to now bundled/built assets. The problem is that Templates are shipped in a different way than static files - the former are injected into a server application and the latter are deployed on a CDN.

πŸ’» Examples

Currently I am doing this manually,

npx parcel build --out-dir=dist-tmp src/index.htpp # template file

# move template files
mkdir -p dist/template
rsync -rv --include '*/' --include '*.htpp' --exclude '*' --prune-empty-dirs dist-tmp/ /dist/template/

# move stati ciles
mkdir -p dist/static
rsync -rv --include '*/' --include '*' --exclude '*.htpp' --prune-empty-dirs dist-tmp/ /dist/static/
devongovett commented 1 month ago

You should be able to read the original name of the main entry asset like this:

import {basename} from 'path';

export default new Namer({
  name({bundle, bundleGraph}) {
    let mainAsset = bundle.getMainEntry();
    if (mainAsset.type === 'htpp')
      return 'templates/' + basename(mainAsset.filePath);
    }
  }
});
sdedovic commented 1 month ago

While the above works, it doesn't completely solve the problem. I still have no way to put the other assets into a subdirectory of dist-dir without the paths in files being borked. Second, I can no longer have a source directory called templates as the name will conflict.

Would you consider my above possible solution? Or potentially a plugin type that runs after all other plugins simply to persist files without other side effects (like Namer plugins have)?