Parcel: Is there a way to build html with relative assets url?

Created on 11 Dec 2017  路  24Comments  路  Source: parcel-bundler/parcel

Choose one: is this a 馃悰 bug report or 馃檵 feature request?

馃檵 feature request

馃 Expected Behavior

When exec parcel build docs/index.html, the generated html should have relative assets url, such as:

<script src="./89ee6b6452b6649c72b85a19637b8362.js"></script>

馃槸 Current Behavior

The url is an absolute path:

<script src="/dist/89ee6b6452b6649c72b85a19637b8362.js"></script>

馃拋 Possible Solution

Is there a way to build html with relative assets url? Maybe some configuration?

馃敠 Context

A common practice is to only host the dist (or public) dir using a static server. But with absolute path, it cannot find the assets resource.

Most helpful comment

Yes, use --public-url when building:
check this PR: https://github.com/parcel-bundler/website/pull/30

All 24 comments

Yes, use --public-url when building:
check this PR: https://github.com/parcel-bundler/website/pull/30

Built files written in ./dist are fine but nothing except the index page gets served by the dev-server.

Example:

test.html:

<h1>test.html</h1>
<script src="test.js"></script>

test.js:

console.log('test.js');

Command, using version 1.10.2:

parcel --public-url '.' test.html

Now http://localhost:1234/ returns the index page as stored in ./dist/test.html. Notice there is no slash in front of the file name, that is the desired outcome of setting --public-url.

<h1>test.html</h1>
<script src="test.e98b79dd.js"></script>

The file ./dist/test.e98b79dd.js looks fine but http://localhost:1234/test.e98b79dd.js _does not_ serve the file.

--public-url ./ still not work.
I just want <script src="./test.e98b79dd.js"></script> instead <script src="test.e98b79dd.js"></script> but a can't do that with --public-url ./ settings - output still without './' =(

For anyone that just really wants to see a './' before the url, what I did was to change the build command (on Mac) to:
parcel build src/index.html --public-url replacethislinewithadot && sed -i '' 's/replacethislinewithadot/./g' dist/index.html

I found no other way to force the '.' in the url.

Relative urls are necessary if one is using parcel to build for a subdomain. This is a necessary feature. @albinotonnina

Wouldn't it also be saver in general to have ./-relative paths per default in the index.html?
I mean, it does not care if sub-directory or not, it will just take the file relative from its location.

I can imagine other scenarios were relative paths are not necessary or need to be altered are way less common than this one.

Note that if you are using something like react-router, the relative paths won't work. Because the href is something like site.com/myApp/router-path and it will try to load site.com/myApp/router-path/styles.css instead of site.com/myApp/styles.css.

Is there any way to have the asset paths be relative to index.html, si it will work wherever you place the index file?

maybe --public-url .

I did it! I managed to make a production build that has react-router and works in any subfolder.
Steps I took:

  • Build parcel with relative paths --public-path ./
  • Use .htaccess to make sure index.html and all assets are loaded correctly when refreshing a virtual path generated by react-router. This was done by simply loading all 404 files from the folder root instead of current path.
  • Make all the links in react-router correct by automatically detecting the app path (basename) on page load based on current location.pathname.

I wrote a more detailed blog post here.

Note, this feels like a very hacky solution, but I did not find any other way to make a fully build application be completely path independent and use only relative paths.

I would recommend deleting your .cache and dist folders whenever you change your --public-url for the changes to actually take effect

Why it's closed? I still don't see a way to produce <script src="./test.e98b79dd.js"></script> output instead <script src="test.e98b79dd.js">

@pawelkedra --public-url ./doesn't work for you?

@mischnic it doesn't, it produces <script src="my-app.0ad7f820.js"> </script>. Looks like ./ part is always skipped

Well,
<script src="./test.e98b79dd.js"></script> and
<script src="test.e98b79dd.js"></script>
do the same thing. The ./ is actually redudant, every path that doesn't start with a protocol or / is relative anyway.

@mischnic it matters if your site is not deployed at the root of the domain, e.g. example.com/site/index.html - without dot browser will try to download all resources from example.com/test.e98b79dd.js, not from example.com/site/test.e98b79dd.js. I can't use --public-url site, I have to consider site part "dynamic", it may be changed for reasons beyond my control.

I agree with @pawelkedra. Having an option to output files that use ./ for paths would be quite useful 馃槉

Any update on this? Why is it closed?

--public-url ./ works for me.

Any updates?

@exsesx Have you tried this? It was the only way I could get it to work.

@EmmaGoodliffe I'm trying, but my index.html points to {public-url}/src...js, but the actual file is not there :c

@exsesx Sorry, I'm not quite sure what you are trying to do 馃.

What is the path in your source index.html and what do you want to change it to?

For anyone that just really wants to see a './' before the url, what I did was to change the build command (on Mac) to:
parcel build src/index.html --public-url replacethislinewithadot && sed -i '' 's/replacethislinewithadot/./g' dist/index.html

I found no other way to force the '.' in the url.

Thanks to @ErikSom
This is my package.json, which is working fine for me.
Inside the build script:
First, I removed the old dist folder
Then, I moved my project's assets to the files folder.
And at the end, I updated the @font-face URL from files/ to ./ path

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "keywords": [],
  "author": "Panbehkar",
  "license": "ISC",
  "scripts": {
    "build": " npm run clean & npm run buildIntoFiles && npm run updatePath",
    "clean": "rmdir /Q /S dist",
    "buildIntoFiles": "parcel build src/index.html --no-source-maps --public-url ./files",
    "updatePath": "sed -i -- 's/files/.\\//g' dist/files/*.css"
  },
  "dependencies": {},
  "devDependencies": {
    "autoprefixer": "^9.8.6",
    "parcel-bundler": "^1.12.4",
    "parcel-plugin-custom-dist-structure": "^1.1.16",
    "postcss-modules": "^3.2.2",
    "prettier": "^2.1.2",
    "sass": "^1.26.11"
  },
  "customDistStructure": {
    "config": {
      "files": [
        ".css",
        ".js",
        ".woff",
        ".png",
        ".jpg"
      ]
    }
  }
}

would recommend deleting your .cache and dist folders whenever you change your --public-url for the changes to actually take effect

I did

$ rm -rf .parcel-cache
$ rm -rf dist
$ parcel build --public-url ./ --dist-dir dist src/html/index.html

And now my file paths are relative (the / is gone).

Was this page helpful?
0 / 5 - 0 ratings