parcel-bundler / parcel

The zero configuration build tool for the web. 📦🚀
https://parceljs.org
MIT License
43.38k stars 2.27k forks source link

Parcel 2: Images #4222

Closed tommmyy closed 4 years ago

tommmyy commented 4 years ago

🐛 bug report

I am not able to load image in JSX file.

🎛 Configuration (.babelrc, package.json, cli command)

yarn build
// package.json
{
    "name": "experiment",
    "version": "1.0.0",
    "license": "MIT",
    "private": true,
    "workspaces": [
        "packages/*"
    ],
    "targets": {
        "main": {},
        "app": {},
        "liferay": {
            "publicUrl": "/o/liferay-amd-loader/",
            "distDir": "../../build/app-demo"
        },
        "browser": {
            "engines": {
                "browsers": [
                    "> 1%",
                    "not dead"
                ]
            }
        }
    },
    "dependencies": {
        "@babel/core": "^7.8.3",
        "babel-eslint": "^10.0.1",
        "babel-plugin-dynamic-import-node": "^2.2.0",
        "babel-preset-react-union": "^0.15.2",
        "liferay-npm-bundler": "^2.13.2",
        "liferay-build-tools": "^0.0.1"
    },
    "scripts": {
        "start": "yarn app-demo start",
        "build": "yarn clean && yarn build:liferay",
        "build_": "yarn clean && yarn build:liferay && yarn bundle",
        "build:liferay": "yarn app-demo build",
        "bundle": "react-union-liferay-build-tools bundle && liferay-npm-bundler",
        "clean": "rimraf build",
        "app-demo": "yarn workspace @union-liferay/app-demo"
    }
}

// packages/app-demo
{
    "name": "@union-liferay/app-demo",
    "version": "0.0.1",
    "private": true,
    "license": "UNLICENSED",
    "main": "src/index.js",
    "browser": "src/index.js",
    "engines": {
        "node": ">=8"
    },
    "dependencies": {
        "@babel/core": "^7.8.4",
        "@babel/polyfill": "^7.8.3",
        "@union-liferay/widget-content": "^0.0.1",
        "@union-liferay/widget-hero": "^0.0.1",
        "document-ready": "^2.0.2",
        "prop-types": "^15.6.2",
        "react": "^16.12.0",
        "react-dom": "^16.12.0",
        "react-hot-loader": "^4.12.18",
        "react-union": "^0.15.2"
    },
    "devDependencies": {
        "parcel": "2.0.0-nightly.119"
    },
    "scripts": {
        "start": "yarn parcel --target=app index.html",
        "build": "yarn parcel build --target=liferay --no-source-maps src/index.js"
    }
}

🤔 Expected Behavior

Should load an image url.

😯 Current Behavior

$ yarn parcel build --target=liferay --no-source-maps src/index.js
$ /experiment/node_modules/.bin/parcel build --target=liferay --no-source-maps src/index.js
🚨 Build failed.
Error: No transformers found for "/experiment/node_modules/@union-liferay/widget-hero/src/components/logo.png".
Error: No transformers found for "/experiment/node_modules/@union-liferay/widget-hero/src/components/logo.png".
    at ParcelConfig.getTransformerNames (/experiment/node_modules/@parcel/core/lib/ParcelConfig.js:127:13)
    at ConfigLoader.loadParcelConfig (/experiment/node_modules/@parcel/core/lib/ConfigLoader.js:88:32)
    at process._tickCallback (internal/process/next_tick.js:68:7)

🔦 Context

Parcel is used in monorepo.

💻 Code Sample

import React from 'react';

import logo from './logo.png';

const Root = () => <img src={logo} />;

export default Root;

🌍 Your Environment

Software Version(s)
Parcel 2.0.0-nightly.119
Node v10.18.1
npm/Yarn 1.19.1
Operating System macosx
DeMoorJasper commented 4 years ago

Currently you'd have to use url:./logo.png but we should probably fallback to it by default.

mischnic commented 4 years ago

we should probably fallback to it by default

This was a deliberate change, see https://github.com/parcel-bundler/parcel/pull/4055:

... Most importantly, it made it impossible for us to ever add support for a new file format without technically causing a breaking change. For example, if we wanted to add an SVG transformer that returned JSX, we could not without breaking existing apps that relied on it returning a URL. ...

tommmyy commented 4 years ago

@mischnic but in build mode, it will return an exception when including the png:

TypeError: Cannot read property 'getBundleURL' of undefined
    at Object.2f227246e2f7deca2cb087b1905a229e (widget-hero.05c09092.js:1)
    at n.parcelRequire.n.parcelRequire (app-demo.aee4f364.js:1)
    at app-demo.aee4f364.js:1

Edit:

Using the following fixes the problem.

--no-scope-hoisting
Banou26 commented 4 years ago

error related to https://github.com/parcel-bundler/parcel/issues/4199

Cristy94 commented 4 years ago

Currently you'd have to use url: ./logo.png but we should probably fallback to it by default.

So, for anyone wondering, that is meant to be the import path:
import logo from 'url: ~/src/logo.png';

LE: Nevermind, this doesn't work. How should we import images so they work with Parcel v2? LE2: Removing the space between url: and ~/src/ fixed the problem.

mischnic commented 4 years ago

First of all, no space between url: and your path. Unless there is another issue I don't know about.

Cristy94 commented 4 years ago

First of all, no space between url: and your path. Unless there is another issue I don't know about.

Removing the space fixed the issue, thank you. I really had to search and read through a lot of GitHub issues before I found out how to load images in v2.

A bit offtopic: So far v2 looks to be very, very buggy. The cache is weird (sometimes I have to delete the cache folder for it to be able to build again), occasionally it throws random errors during build and I do have to change parts of my code to switch from v1 to v2, which is weird for a zero-configuration bundler.

Even now, I run parcel, it says build is fine, I save one file without making any changes, it says build failed and now throws the error which also existed on the initial "successful" build.

willstott101 commented 4 years ago

Is there a way with config to make url: not required? I can see the stability benefits of not being too magical here, but in my case I want my library's examples to be build-able very simply using parcel, but also support embedding within a larger web-pack (dojo) project. Presumably there is a way to explicitly match transformers for images in the config, but I'm struggling with small amount of v2 docs

mischnic commented 4 years ago

Is there a way with config to make url: not required

Yes .parcelrc:

{
    "extends": "@parcel/config-default",
    "transformers": {
        "*": ["@parcel/transformer-raw"]
    }
}

(The only reason for the explicit protocol is that supporting another file type natively would be a breaking change because doing import ... from "./xyz.foo wouldn't return an url anymore).

willstott101 commented 4 years ago

Thankyou! I think requiring being explicit does make sense for something as open ended as file types.

Am now using .parcelrc to get what I want:

{
    "extends": "@parcel/config-default",
    "transformers": {
        "*.png": ["@parcel/transformer-raw"]
    }
}
mischnic commented 4 years ago

Closing this since it has turned into an migration Q&A.

Please open a new issue with a reproduction if TypeError: Cannot read property 'getBundleURL' of undefined is still happening.

berkant commented 4 years ago

How to import multiple images?

I was able to do it like this in Parcel v1: import * as sprites from './assets/*.png';