HTML

Parcel includes first-class support for HTML out of the box. HTML files are often the entry file that you provide to Parcel, and all dependencies including JavaScript, CSS, images, and links to other pages are followed from there to build your entire app.

Dependencies

#

Parcel detects most references in HTML to other files (such as <script>, <img>, <video> or <meta property="og:image">) and processes them as well. These references are rewritten so that they link to the correct output files.

File names are resolved relative to the current HTML file, but you can also use absolute and tilde specifiers. See Dependency resolution for details.

Stylesheets

#

The <link rel="stylesheet"> element can be used to reference stylesheets from HTML. You can reference a CSS file, or any other file that compiles to CSS such as SASS, Less, or Stylus.

index.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./style.less" />
</head>
<body>
<h1>My Parcel app</h1>
</body>
</html>
style.less:
h1 {
color: darkslategray;
}

See the CSS docs for details on how CSS is processed by Parcel.

Scripts

#

The <script> element can be used to reference a script file from HTML. You can reference a JavaScript file, or any other file that compiles to JavaScript such as TypeScript, JSX, or CoffeeScript.

index.html:
<!DOCTYPE html>
<html>
<head>
<script type="module" src="app.ts" />
</head>
<body>
<h1>My Parcel app</h1>
</body>
</html>
app.ts:
console.log("Hello world!");

The type="module" attribute should be used to indicate that a file is an ES module or CommonJS file. If it is omitted, then the referenced file is treated as a classic script. See Classic scripts for more information about this.

When a <script type="module"> is used and some of your browser targets do not support ES modules, Parcel compiles it to a classic script with the defer attribute instead.

Parcel also supports the async and defer attributes of the <script> element. When a script is async, it may load in an arbitrary order at runtime. Therefore, Parcel treats async scripts as "isolated”. This means that async scripts cannot share any dependencies with other scripts on the page, which may result in duplication of modules. For this reason, it's better to avoid async scripts except in specific circumstances.

The defer attribute has a similar effect as async (non render-blocking), but guarentees that scripts are executed in the order they are defined in the HTML file. When using <script type="module">, defer is automatically enabled and does not need to be declared.

See the MDN docs for the <script> element for more info, and the JavaScript docs for details on how Parcel processes JavaScript.

Images

#

Parcel supports images referenced via the <img> element. The src attribute can be used to reference an image file.

<img src="image.jpg" alt="An image" />

Parcel also supports the srcset attribute, which allows referencing multiple versions of an image for different sizes or resolutions.

<img src="logo@1x.png" srcset="logo@2x.png 2x" alt="logo" />

In addition, Parcel supports the <picture> element, which allows even more flexibility for providing multiple alternative images via the <source> element.

Parcel’s image transformer can also be used to generate multiple versions of an image from a single source file. This is done using query parameters to provide the width, height, and format to convert and resize the source image.

<picture>
<source
type="image/webp"
srcset="image.jpg?as=webp&width=400, image.jpg?as=webp&width=800 2x"
/>

<source
type="image/jpeg"
srcset="image.jpg?width=400, image.jpg?width=800 2x"
/>

<img src="image.jpg?width=400" width="400" />
</picture>
#

Parcel supports the <a> element to link to another page from an HTML file.

<a href="other.html">Other page</a>

The <iframe> element can be used to embed an HTML page inside another.

<iframe src="iframe.html"></iframe>

While other assets referenced from an HTML file will include a content hash in their compiled filename by default, files referenced by an <a> or <iframe> element will not. That's because these URLs are typically human readable, and need to have a stable name over time. Bundle naming can be overridden by Namer plugins.

Video, audio, and other assets

#

The <video>, <audio>, <track>, <embed>, and <object> elements are supported. The referenced URLs are processed by Parcel and rewritten to include a content hash.

Open Graph and Schema.org metadata

#

Parcel supports Open Graph, Twitter Cards, VK, Schema.org, and Microsoft pinned site metadata defined using the <meta> tag. Images and other URLs referenced in these elements are processed by Parcel and rewritten to link to the correct output files. Since these URLs are often cached by external services, most of them do not include a content hash.

<meta property="og:image" content="100x100.png" />

JSON-LD

#

Parcel supports JSON-LD metadata embedded in HTML via <script> tags. Images and other URLs referenced in JSON-LD are processed by Parcel and rewritten to include a content hash. This is handled by the @parcel/transformer-jsonld plugin, which is included in Parcel's default config.

In this example, the image referenced from the logo object will be processed by Parcel.

<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "LocalBusiness",
"name": "Joe's Pizza",
"description": "Delicious pizza for over 30 years.",
"telephone": "555-111-2345",
"openingHours": "Mo,Tu,We,Th,Fr 09:00-17:00",
"logo": {
"@type": "ImageObject",
"url": "images/logo.png",
"width": 180,
"height": 120
}
}
</script>

Web manifests

#

The <link rel="manifest"> element is supported to reference a Web manifest. This is a JSON file that includes various metadata about the app, and allows it to be installed to the user's home screen or desktop. Parcel processes the URLs referenced in the icons and screenshots keys in this file, as well as the icons of each item in shortcuts and file_handlers. Web manifests may be written in either a .json or .webmanifest file.

<link rel="manifest" href="manifest.json" />

Inline scripts and styles

#

<script> and <style> tags with text content are also processed just like standalone files, and the generated bundles are inserted back into the HTML file. The type="module" attribute on script tags works just as described above for external scripts. However, if some of your browser targets don't support ES modules natively, Parcel will compile inline scripts to a non-module script and will not output a <script type="module">.

index.html:
<!DOCTYPE html>
<html>
<body>
<style>
@import "./style.scss";
</style>
<script type="module">
import value from "./other.ts";
console.log(value);
</script>
</body>
</html>

Note: Use this sparingly, as big inline scripts/styles can be detrimental to the (perceived) load speed.

Inline style attribute

#

The style attribute can be used on any HTML element to define CSS styles. Parcel will process the inline CSS, and insert the result back into the style attribute. This includes following referenced URLs such as background images, as well as transforming modern CSS for your target browsers.

<div style="background: url(background.jpg)">Hello!</div>

Inline SVG

#

Parcel supports inline SVG in HTML. Images referenced via the <image> element and dependencies referenced via the <use> element are supported, and inline scripts and styles within the SVG are also processed as described above.

<!DOCTYPE html>
<html>
<body>
<svg xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" width="50" height="50" fill="red" />
<use xlink:href="icon.svg" />
</svg>
</body>
</html>

Parallel scripts and styles

#

When referencing a script or style, sometimes Parcel will need to insert another dependent file into the compiled HTML file. For example, when referencing a JavaScript file which imports a CSS file, Parcel will insert a <link> element before the <script> to load this stylesheet in parallel with the JavaScript.

index.html:
<!DOCTYPE html>
<html>
<head>
<script type="module" src="app.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
app.js:
import "./app.css";

let app = document.createElement("div");
app.className = "app";
app.textContent = "My Parcel app!";
root.appendChild(app);
app.css:
.app {
background: red;
}

Compiled HTML:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/ejev5k34.css" />
<script type="module" src="/app-7yoxqbr3.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>

This may also occur with scripts. For example, if two pages depend on the same JavaScript library (e.g. React or Lodash), it may be split out into its own bundle and loaded separately. Parcel will insert a <script> tag into the compiled HTML to load this "shared bundle" in parallel. See Code Splitting for more details.

PostHTML

#

PostHTML is a tool for transforming HTML with plugins. PostHTML support is provided by the @parcel/transformer-posthtml plugin, which is not included in the default Parcel config. Install it along with any PostHTML plugins you need:

yarn add @parcel/transformer-posthtml@next posthtml-doctype --dev

Then, add it to your .parcelrc so that it runs before Parcel's builtin HTML transformer:

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"*.html": ["@parcel/transformer-posthtml", "..."]
}
}

You can configure PostHTML by creating a configuration file using one of these names: .posthtmlrc (JSON), .posthtmlrc.json, .posthtmlrc.js, .posthtmlrc.mjs, .posthtmlrc.cjs, posthtml.config.js, posthtml.config.mjs, or posthtml.config.cjs. A posthtml key in package.json is also supported.

For example, create a config file:

.posthtmlrc:
{
"plugins": {
"posthtml-doctype": { "doctype": "HTML 5" }
}
}

Plugins are specified in the plugins object as keys, and options are defined using object values. If there are no options for a plugin, just set it to an empty object instead.

Alternatively, PostHTML options can be specified inline in your .parcelrc. When present, this takes precedence over any PostHTML config file.

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"*.html": [
{
"plugin": "@parcel/transformer-posthtml",
"config": {
"plugins": {
"posthtml-doctype": { "doctype": "HTML 5" }
}
}
},
"..."
]
}
}

This example uses posthtml-include to inline another HTML file.

.posthtmlrc:
{
"plugins": {
"posthtml-include": {}
}
}
index.html:
<html>
<head>
<title>Home</title>
</head>
<body>
<include src="header.html"></include>
<main>My content</main>
</body>
</html>
header.html:
<header>This is my header</header>

posthtml.config.js

#

For some plugins that require passing a function as a configuration option, or to set up plugins based on process.env.NODE_ENV, you need to use a posthtml.config.js file for configuration instead of .posthtmlrc.

This example uses posthtml-shorten to shorten URLs using a custom shortening function.

yarn add posthtml-shorten --dev
posthtml.config.js:
module.exports = {
plugins: {
"posthtml-shorten": {
shortener: {
process: function (url) {
return new Promise((resolve, reject) => {
resolve(url.replace(".html", ""));
});
},
},
tag: ["a"], // Allowed tags for URL shortening
attribute: ["href"], // Attributes to replace on the elements
},
},
};
index.html:
<html>
<head>
<title>Home</title>
</head>
<body>
<a href="http://example.com/test.html">Example</a>
</body>
</html>

Production

#

In production mode, Parcel includes optimizations to reduce the file size of your code. See Production for more details about how this works.

Minification

#

In production mode, Parcel automatically minifies your code to reduce the file sizes of your bundles. Parcel uses its builtin HTML minifier, which also minifies inline SVG and JSON.

To configure it, set the optimize option of @parcel/transformer-html in your .parcelrc. Set it to false to disable HTML minification, or to an object of options.

For example to retain HTML comments

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"*.html": [
{
"plugin": "@parcel/transformer-html",
"config": {
"optimize": {
"removeComments": false
}
}
}
]
}
}

or to not minify SVG elements.

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"*.html": [
{
"plugin": "@parcel/transformer-html",
"config": {
"optimize": {
"minifySvg": false
}
}
}
]
}
}

The following options are supported, and are all enabled by default: collapseAttributeWhitespace, collapseWhitespace, deduplicateAttributeValues, removeComments, removeEmptyAttributes, minifyJson, removeRedundantAttributes, collapseBooleanAttributes, normalizeAttributeValues, and sortAttributesWithLists. The minifySvg option can also be set to an object of options for the SVG minifier.