I'm using typescript and when i upgrade parcel from 1.2.0 to 1.3.1 _(I've tried with 1.3.0 as well)_ the moment.js
library starts complaining about moment
not being a function.
// package.json
{
"scripts": {
"start": "parcel index.html --out-dir temp/"
},
"dependencies": {
"moment": "^2.20.1",
"parcel-bundler": "1.3.0",
"typescript": "^2.6.2"
}
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<script src="./app.ts"></script>
</body>
</html>
//app.ts
import * as moment from 'moment';
console.log( moment() );
_No tsconfig.json_
I would expect a moment
object to be printed to the console.
With parcel v1.2.0
the moment
object is printed just fine. But with parcel v1.3.0
or v1.3.1
it throws a TypeError.
b6623a1acd83678d58392c21229a4b42.js:6473 Uncaught TypeError: moment is not a function
at Object.require.2.moment (b6623a1acd83678d58392c21229a4b42.js:6473)
at newRequire (b6623a1acd83678d58392c21229a4b42.js:41)
at require.4 (b6623a1acd83678d58392c21229a4b42.js:66)
at b6623a1acd83678d58392c21229a4b42.js:71
Gist of all files used to recreate bug: https://gist.github.com/Olian04/ce4e23c11a17d60c9a39247a879e54c7
| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.2.0 & 1.3.0 & 1.3.1
| Node | 9.3.0
| npm/Yarn | 5.5.1 / 1.3.2 _(I've tried with both)_
| Operating System | Ubuntu 17.04
Unsure yet exactly why the default behavior has changed, but the following is a workaround:
// change this
import * as moment from 'moment';
// to this
import moment from 'moment';
OR
// change this
console.log ( moment() );
// to this
console.log( moment.default() );
https://momentjs.com/docs/#/use-it/typescript/
The addition of the following lines resulted in the "breaking change". Commenting them out in master restores previous functionality:
Original: #298
PR: #299
Follow-up: #359
@fathyb @devongovett
For reference, moment's package.json
:
"main": "./moment.js",
"jsnext:main": "./src/moment.js",
@brandon93s
import moment from 'moment';
isn't valid ts, since moment
doesn't provide a default export.
@Olian04 ~moment
is exported as default
in it's ES6 form, see the code (referenced by jsnext:main
). The problem here is that the main
field points to a UMD module, which uses module.exports
.~
edit: Didn't understood you were talking about ts. Yeah allowSyntheticDefaultImports
is the way to go. Parcel uses Babel which will automatically find if a module is ES6 or CommonJS and export the correct value accordingly, so it's safe to use :
var _moment = require("moment");
var _moment2 = _interopRequireDefault(_moment);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@fathyb yea, parcel users Babel for js files. But it uses tsc for ts files. So I'm not really sure how referring to Babel is relevant. Or am I missing something?
@brandon93s what exactly makes this a question? o_0
@Olian04 TypeScript sources are treated like any JavaScript files once they are processed. If you use "module": "es6"
your import
declarations are transformed by Babel to require
calls with default
interoperability like described above.
@Olian04 - mostly a parcel team question to spawn discussion on how to handle this. The change that lead to this behavior is valid, and consumers can get past it with appropriate imports. However, it won't be compatible in many cases with existing code so we'll need to determine a path forward for handling it.
ah. so parcel doesnt work with typescript imports?
Any update on this one?
This is also breaking my project. I need import moment from 'moment';
for Parcel, but import * as moment from 'moment';
for running tests (which compile from TS directly). Any help would be appreciated.
moment
. I encourage you to try it while it's being reviewed as it changes how Parcel interpret import * as
.I'm also using typescript in my projects now. I have experienced the same error as yours, Typescript is upgraded to version 2.7
, it supports es6 module
. so I solved the same problem as yours, try version up for typescript, and add tsconfig.json
{
"esModuleInterop": true
}
I solved moment js problem. try this! 馃憤
I've tried to use two react date UI packages that require('moment') and are broken by the es6'fying of the returned moment object (if I understand the issue correctly) by Parcel/Babel
i.e. { default: moment, __esModule: true }
What exactly is happening, and is there anything I can do now to stop that happening? Such as a .babelrc option?
Not using typescript.
Not realistic to have to create forks of packages that then use moment to work around this.
@Olian04
I would expect a moment object to be printed to the console.
Your expectation is incorrect. If it worked in previous versions of parcel then that was a 馃悰.
Most helpful comment
I'm also using typescript in my projects now. I have experienced the same error as yours, Typescript is upgraded to version
2.7
, it supportses6 module
. so I solved the same problem as yours, try version up for typescript, and add tsconfig.jsonI solved moment js problem. try this! 馃憤