parcel-bundler / parcel

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

Render function import for JSX is removed if it's not explicitly used #1487

Closed marcusball closed 6 years ago

marcusball commented 6 years ago

🐛 bug report

I am trying to use Hyperapp with JSX. I followed this guide for most of my set up. I'm not experienced with the JS so I'm sorry if I misdiagnosed this as a Parcel issue if it's actually a bug in a dependency or me misconfiguring something.

Basically, hyperapp uses the h function for virtual-DOM creation, and I have configured babel to use that when transforming JSX.

index.tsx:

import { h, app } from 'hyperapp';

const root = document.getElementById('root') as HTMLElement;

// Equivalent to: `const view = () => h('h1',{},'Hello world');`
const view = () => (
    <h1>Hello world</h1>
);

app({}, {}, view, root);

The problem is that when I run this in my browser, I will receive a ReferenceError: h is not defined error and nothing will render.

However, the code will run properly if I have explicitly used the h function anywhere in code. This example will run fine:

import { h, app } from 'hyperapp';

const _ = h(''); // explicitly use `h`, even if it does nothing. 

const root = document.getElementById('root') as HTMLElement;

// Equivalent to: `const view = () => h('h1',{},'Hello world');`
const view = () => (
    <h1>Hello world</h1>
);

app({}, {}, view, root);

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

.babelrc:

{
    "presets": [
        "env"
    ],
    "plugins": [
        [
            "transform-react-jsx",
            {
                "pragma": "h"
            }
        ]
    ]
}

package.json:

{
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-plugin-transform-react-jsx": "^6.24.1",
    "babel-preset-env": "^1.7.0",
    "typescript": "^2.9.1"
  },
  "scripts": {
    "build": "parcel build src/index.html",
    "start": "parcel src/index.html",
    "dev": "parcel watch src/index.html",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "hyperapp": "^1.2.6"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": [
      "dom",
      "es2015",
      "es2015.collection"
    ], /* Specify library files to be included in the compilation. */
    "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    "importHelpers": true, /* Import emit helpers from 'tslib'. */
    "strict": true, /* Enable all strict type-checking options. */
    "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  }
}

Commands

yarn start and yarn build which alias to:

parcel src/index.html and parcel build src/index.html.

🤔 Expected Behavior

The h function import should be included in the bundled code.

😯 Current Behavior

The h function is not included. My assumption is that because the h import is not explicity used, it it being stripped as an unused import, even though it'll be used once the babel transform is complete.

🔦 Context

This is mostly just annoying, but isn't a huge problem. Adding a dummy use of the function is hacky, but doesn't prevent me from getting work done.

💻 Code Sample

See above, let me know if I left out any necessary files.

src/index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Example</title>
</head>

<body>
    <div id="root"></div>
    <script src="./index.tsx"></script>
</body>

</html>

🌍 Your Environment

Software Version(s)
Parcel 1.8.1
Node v10.3.0
npm/Yarn Yarn 1.7.0
Operating System Linux archlabs 4.16.12-1-ARCH
Typescript 2.9.1
DeMoorJasper commented 6 years ago

This is strange, babel transformations occur before minification, there shouldn't be any code removal before that step.

Could you provide a minimal repo for reproduction?

I would say babel transforms are not being applied but than you wouldn't get h is not defined in the browser so it's probably not that

marcusball commented 6 years ago

All of the code snippets above are enough to reproduce the issue; I've attached an archive of them, let me know if an actual git repo would be preferrable.

You should be able to just npm install/yarn install to set up the repo.

When you run Parcel the issue should be present; if you uncomment line 3 of src/index.tsx the code should run correctly.

problem-demo.tar.gz

marcusball commented 6 years ago

I took a bunch of time today to dig through the code and eventually found that it was the Typescript compiler that was stripping the import line (https://github.com/Microsoft/TypeScript/issues/24731).