Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundle is missing exports #7622

Open
halvardssm opened this issue Jan 29, 2022 · 6 comments
Open

Bundle is missing exports #7622

halvardssm opened this issue Jan 29, 2022 · 6 comments

Comments

@halvardssm
Copy link

halvardssm commented Jan 29, 2022

🐛 bug report

Hi! I am trying to refactor an npm package from js/jquery to ts, and in the update process, I wanted to use Parcel as bundler due to its ease of use and zero config. When using parcel build, the code gets generated, but functions and enums are not accessible in the bundle nor exported.

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

package.json

{
  "packageManager": "yarn@3.1.1",
  "name": "clippy.js",
  "version": "2.0.0",
  "source": "lib/index.ts",
  "main": "dist/main.js",
  "module": "dist/module.js",
  "types": "dist/types.d.ts",
  "files": [
    "dist/*"
  ],
}

tsconfig.json

{
  "compilerOptions": {
    "module": "ESNext",
    "target": "ES3",
    "strict": true,
    "allowJs": true,
    "checkJs": true,
    "sourceMap": true,
    "declaration": true,
    "outDir": "dist",
    "moduleResolution": "node",
    "jsx": "react-jsx",
    "lib": ["esnext","DOM"]
  },
  "include": ["lib"]
}

🤔 Expected Behavior

Enums and functions should be exported from and be accessible in the bundle

😯 Current Behavior

Uncaught (in promise) TypeError: $dF6ai.getAgent is not a function
    $38cce2cce4d8c489$export$74cd1f32039e2d7f clippy.ts:13
    App index.9978ec32.js:1018
    React 5
    unstable_runWithPriority scheduler.development.js:468
    React 3
    workLoop scheduler.development.js:417
    flushWork scheduler.development.js:390
    performWorkUntilDeadline scheduler.development.js:157
    L7NvB scheduler.development.js:180
    L7NvB scheduler.development.js:645
    newRequire index.9978ec32.js:71
    localRequire index.9978ec32.js:84
    k1C1m index.js:6
    newRequire index.9978ec32.js:71
    localRequire index.9978ec32.js:84
    React 2
    newRequire index.9978ec32.js:71
    localRequire index.9978ec32.js:84
    ["1mpsW"]< React
    newRequire index.9978ec32.js:71
    localRequire index.9978ec32.js:84
    ipvmp index.tsx:1
    newRequire index.9978ec32.js:71
    <anonymous> index.9978ec32.js:122
    <anonymous> index.9978ec32.js:145

💁 Possible Solution

🔦 Context

💻 Code Sample

https://github.com/halvardssm/clippy.js

To reproduce:

  1. Clone and checkout branch parcel-repro
  2. Run yarn install
  3. Run yarn pack
  4. Add "clippy": "file:./clippy.js-v2.0.0.tgz", to deps
  5. Run yarn install
  6. Run yarn start and visit the page in the browser
  7. Inspect the console to see errors.

To verify that the issues are only happening when bundling with parcel, checkout branch refactor and start the app.

🌍 Your Environment

Software Version(s)
Parcel 2.2.0
Node 16.13.2
npm/Yarn Yarn 3.1.1 PNP
Operating System MacOS & Windows 11
@CalamityAdam
Copy link

CalamityAdam commented Feb 2, 2022

I am having the same issue. parts of a dependency are being "stripped away" during build and do not exist in the bundle. they do, however, exist in the source maps. so local development works fine. but when using just the bundle (via the build output), pieces are completely missing.

seems to be a possible duplicate of #7580 and #7555

🐛 bug report

using redux-toolkit query in a react 17 app, one of the functions available as an export from @reduxjs/toolkit/query/react, fetchBaseQuery, can not be found in the build, with the following error being thrown in the browser:

Uncaught TypeError: Gh.fetchBaseQuery is not a function

strangely, when looking through the build's bundles, the definition for that function can be found in the source maps. however, in the bundled javascript file, the only reference to fetchBaseQuery can be found in the line causing the above error to be thrown. I can see when Gh is defined and built out, but fetchBaseQuery is not a part of it. furthermore, (referencing the following screenshots) it appears as if fetchBaseQuery should be found on qh instead of Gh, based on the bundle.

description screenshot
bundled source code line causing the error to be thrown source code line throwing error
bundled source code showing where Gh is defined source code showing where Gh is defined
source mapped output showing the original code (where error is being thrown) source mapped code showing original code throwing error

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

babel.config.json (only used for jest tests)

{
  "env": {
    "test": {
      "presets": [
        "@parcel/babel-preset-env",
        "@babel/preset-typescript",
        "@babel/preset-react"
      ]
    }
  }
}

.parcelrc.json

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.{js,mjs,jsm,jsx,es6,cjs,ts,tsx}": [
      "@parcel/transformer-babel",
      "@parcel/transformer-js",
      "@parcel/transformer-react-refresh-wrap"
    ]
  }
}

build script:

"build": "parcel build src/index.html --public-url /app --no-source-maps",

package.json (everything is up to date):

{
  ...
  "dependencies": {
    "@auth0/auth0-react": "^1.9.0",
    "@optimizely/react-sdk": "^2.8.0",
    "@ramsey-design-system/button": "^2.0.1",
    "@ramsey-design-system/icon": "^2.0.0",
    "@ramsey-design-system/icons": "^2.3.1",
    "@ramsey-design-system/link": "^1.3.1",
    "@reduxjs/toolkit": "^1.7.1",
    "apophenia-javascript-logger": "^2.0.3",
    "gazelle-design-system": "^1.16.3",
    "postcss-modules": "^4.3.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.6",
    "react-router-dom": "^6.2.0",
    "redux": "^4.1.2",
    "styled-components": "^5.3.3",
    "typescript": "^4.5.5"
  },
  "scripts": {
    "clean": "rm dist/* .parcel-cache/* || true",
    "build": "parcel build src/index.html --public-url /app --no-source-maps",
    "start": "parcel src/index.html --open --port 3000",
    "start-fresh": "yarn clean && yarn build && yarn start",
    "test": "jest",
    "test:watch": "jest --watch"
  },
  "devDependencies": {
    "@babel/core": "^7.16.12",
    "@babel/preset-react": "^7.16.7",
    "@babel/preset-typescript": "^7.16.7",
    "@googlemaps/jest-mocks": "^2.3.0",
    "@parcel/babel-preset-env": "^2.2.1",
    "@parcel/transformer-sass": "^2.2.1",
    "@ramseyinhouse/eslint-config": "^1.0.4",
    "@ramseyinhouse/stylelint-config": "^1.1.0",
    "@testing-library/jest-dom": "^5.16.1",
    "@testing-library/react": "^12.1.2",
    "@testing-library/user-event": "^13.5.0",
    "@types/google.maps": "^3.47.3",
    "@types/jest": "^27.4.0",
    "@types/react": "^17.0.38",
    "@types/react-dom": "^17.0.11",
    "@types/react-router-dom": "^5.3.3",
    "@types/styled-components": "^5.1.21",
    "@typescript-eslint/eslint-plugin": "^5.10.2",
    "@typescript-eslint/parser": "^5.10.2",
    "autoprefixer": "^10.4.2",
    "axios": "^0.25.0",
    "babel-jest": "^27.4.6",
    "babel-plugin-styled-components": "^2.0.2",
    "eslint": "^8.8.0",
    "eslint-plugin-react-hooks": "^4.3.0",
    "jest": "^27.4.7",
    "jest-styled-components": "^7.0.8",
    "modules": "^0.4.0",
    "msw": "^0.36.8",
    "parcel": "^2.2.1",
    "plugins": "^0.4.2",
    "postcss": "^8.0.0",
    "postcss-custom-properties": "^12.1.4",
    "postcss-import": "^14.0.2",
    "postcss-url": "^10.1.3",
    "prettier": "^2.5.0",
    "redux-devtools": "^3.7.0",
    "stylelint": "^14.3.0",
    "stylelint-config-prettier": "^9.0.3",
    "stylelint-config-sass-guidelines": "^9.0.1",
    "stylelint-config-standard-scss": "^3.0.0",
    "stylelint-config-styled-components": "^0.1.1",
    "stylelint-order": "^5.0.0",
    "stylelint-processor-styled-components": "^1.10.0",
    "typescript-plugin-styled-components": "^2.0.0"
  },
  ...
}

🤔 Expected Behavior

fetchBaseQuery definition should be found and no error should be thrown. the definition of fetchBaseQuery should be included in the bundle

😯 Current Behavior

fetchBaseQuery definition can not be found.
note in the source maps, fetchBaseQuery can be found, thus it works fine in local development. however, in the bundled js file, the definition for fetchBaseQuery can not be found.

💁 Possible Solution

n/a. sorry 😕

🔦 Context

this one is frustratingly misleading. the old "works on my machine"! the 'missing' function is defined properly in the source maps, thus local development sees no issue. however when deployed to a production environment via parcel build ... --no-source-maps the whole application tanks because of that uncaught error

💻 Code Sample

this is probably not helpful, but here is how the missing function is being used:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const API_BASE_URL = 'https://somewebsite.com/api';

const searchApi = createApi({
  reducerPath: 'searchApi',
  baseQuery: fetchBaseQuery({ baseUrl: API_BASE_URL }),
  endpoints: (builder) => ({
    getProsByProgramAndZip: builder.query({
      query: ({ program, zip }) =>
        `/pro/search?programKey=${program}&postalCodes=${zip}`,
    }),
  }),
});

const { useGetProsByProgramAndZipQuery } = searchApi;

export { API_BASE_URL, searchApi, useGetProsByProgramAndZipQuery };

🌍 Your Environment

Software Version(s)
Parcel 2.2.1
Node 14.18.1
Yarn 1.22.17
Operating System macOS Monterey 12.1

@CalamityAdam
Copy link

CalamityAdam commented Feb 2, 2022

did some more digging on this. looks like in my case above the issue is that parcel (or, parcel-bundler?) is not recognizing aliased files.
@reduxjs/toolkit/query/react is just doing export * from '@reduxjs/toolkit/query', so for some reason parcel is not recognizing those exports.

When I change this line:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

to this:

import { createApi } from '@reduxjs/toolkit/query/react';
import { fetchBaseQuery } from '@reduxjs/toolkit/query';

which is nothing more than explicit imports rather than using aliased (is that the right term?) imports, the bundler correctly grabs the definition of fetchBaseQuery.

the super strange thing is that the correct definition of fetchBaseQuery can be found in the source maps, but not in the minified bundle. so, in local development it works fine (using source maps) but deployed it does not (using only the bundle).

I don't know where to go from this, but I feel like this is some pretty good context to diagnose exactly what's failing in the bundler!

@mischnic
Copy link
Member

mischnic commented Mar 3, 2022

Reproduction for that RTK problem:

// index.js
import { createApi, fetchBaseQuery } from "./lib";
console.log(createApi, fetchBaseQuery);

// lib/package.json
{"sideEffects": false}

// lib/index.js
console.log(this);
export * from "./lib1.js";
export var createApi = 123;

// lib/lib1.js
export function fetchBaseQuery(){}

@starpit
Copy link

starpit commented Apr 18, 2022

I'm trying to figure out whether our issue is the same as this. I think so?

mynpm/index.ts:

import * as GraphApi from "./graph"
export { GraphApi }

publish this as mynpm

apiconsumer.ts

import { GraphApi } from 'mynpm'

Module '"mynpm"' has no exported member 'GraphApi'.

Workarounds?

I'm actually not sure how to work around this issue. One can hack it for non-types (such as re-exporting functions), but typescript does not allow exporting types as part of a const. And, when I try

export * as GraphApi from './graph'

I get, from parcel

@parcel/transformer-typescript-types: node.exportClause.elements is not iterable

i.e. #5911

starpit added a commit to starpit/madwizard that referenced this issue Apr 18, 2022
We need to allow fine-grained imports, and parcel has several bugs that block doing this in the normal way:
parcel-bundler/parcel#7622
parcel-bundler/parcel#5911

This PR also enables validation and progress apis.
starpit added a commit to guidebooks/madwizard that referenced this issue Apr 18, 2022
We need to allow fine-grained imports, and parcel has several bugs that block doing this in the normal way:
parcel-bundler/parcel#7622
parcel-bundler/parcel#5911

This PR also enables validation and progress apis.
@autra
Copy link

autra commented Jul 10, 2023

We reproduce it with https://gitlab.com/giro3d/giro3d-sample-application. Our workaround is to use --no-optimize

@drewcorlin1
Copy link

drewcorlin1 commented Jul 19, 2023

I'm running into a similar issue on Parcel 2.9.3, where I have a module in my application which exports a single object (and depends on no other modules).

export const routes = {
  home: () => '/',
  search: () => '/search',
  account: () => '/account',
  login: () => '/login',
  forgotPassword: () => '/forgot-password',
  notFound: () => '/not-found',
};

If I run parcel with optimization enabled this module gets "optimized out". Other places that reference this module then end up with this routes just being an empty object, so they fail trying to call routes.home() since routes.home is undefined.

Interestingly if I do something else to reference this object, like console.log(routes) within this module, then it behaves properly.

Similarly if I run with --no-optimize the problem goes away, but that is not ideal. Please let me know if I can provide any more information!

Edit:
Trying to add more context if it's helpful. Things that do "fix" this problem

  • Adding console.log(routes) in that same module
  • Adding JSON.stringify(routes) in that module

Things that do not

  • Assigning a single field to that object (routes.home = () => '/';)

This was not always the case. I set this project up a couple of months ago with no issue. I recently cleared out my node_modules and package-lock, and reinstalled all dependencies. I now see this issue. I'm still trying to understand what dependency changed to uncover this, as I have a huge diff in my package-lock. Will update this comment as I find anything

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants