I was trying to figure out which repo this issue belongs in, but I'm not sure. My question is: is it possible to use lodash-es with Next.js?
import { now } from 'lodash-es';
export default () => <div>{now()}</div>;
At initial render this fails with:
index.js?483da04:97 Unexpected token export
/Users/silvenon/Code/lodash-es/node_modules/lodash-es/lodash.js:10
export { default as add } from './add.js';
^^^^^^
SyntaxError: Unexpected token export
at createScript (vm.js:74:10)
at Object.runInThisContext (vm.js:116:10)
at Module._compile (module.js:533:28)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:503:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
at Module.require (module.js:513:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/Users/silvenon/Code/lodash-es/.next/dist/pages/index.js:11:17)
But works after a hot reload (when I save a file change).
Next.js webpack config doesn't transform node_modules using Babel, you need to import already transpiled dependencies.
Like @sergiodxa said :)
So how can I fix this? Thanks.
@lednhatkhanh one workaround is babel-plugin-lodash. I haven't used Next.js in a while, so I don't remember if you can modify Babel config.
You'll get tree shaking with straight lodash if you do the following:
import now from 'lodash/now';
https://stackoverflow.com/questions/35250500/correct-way-to-import-lodash
I tested this with next-bundle-analyzer and I can see that it only bundles the module I imported.
@sergiodxa @timneutkens lodash-es _is_ already transpiled. Open any file in https://github.com/lodash/lodash/tree/es and you'll see no ES6 features whatsoever, except for import/export which are supposed to be handled by _webpack_ not _babel._
Anyway, using lodash-es is not a good idea anyway until Next.js has upgraded to webpack 4 which supports sideEffects: false.
Can this be re-opened now that canary uses webpack 4?
So I guess the problem is our externals configuration for the server side. This explicitly says we shouldn't transpile any modules inside node_modules in the server-side compilation, the reason for this is that it would be extremely slow to bundle every node_modules module into every page it's used in.
Correct! I managed to get lodash running both on the server and in the browser by using this next.config.js:
module.exports = {
webpack: config => ({
...config,
externals: Array.isArray(config.externals)
? config.externals.map(
fn =>
typeof fn === "function"
? (context, request, callback) => {
// We use lodash-es in the browser for tree-shaking, but
// switch to the regular lodash on the server to avoid having
// to transpile `import`/`export` there.
if (request === "lodash-es") {
return callback(null, "commonjs lodash");
}
return fn(context, request, callback);
}
: fn,
)
: config.externals,
}),
};
However, the browser bundle became much bigger than when using babel-plugin-lodash + lodash-webpack-plugin, so I switched back to that. Not sure if webpack's tree shaking isn't fully fleshed out yet, or if I'm missing something.
Here's how I solved it:
// next.config.js
const withTM = require('next-transpile-modules');
module.exports = withTM({
transpileModules: ['lodash-es']
);
(all modules are ignored, except lodash-es, which is transpiled using Webpack and Babel)
Going to track this in #706
Most helpful comment
Here's how I solved it:
(all modules are ignored, except
lodash-es, which is transpiled using Webpack and Babel)