Error in build: Named export. The requested module is a CommonJS module in antfu Vite SSG
Jan 29, 2023
Explanation of the problem
The issue at hand is that the build process is failing when using the @googlemaps/js-api-loader package in a Vite-SSG project. The code works as expected in development mode, but when building, the following error message is thrown:
[vite-ssg] An internal error occurred. [vite-ssg] Please report an issue, if none already exists: https://github.com/antfu/vite-ssg/issues file:///usr/local/playground/@codermar/monorepo/marynela.com/.vite-ssg-temp/main.mjs:30 import { Loader } from “@googlemaps/js-api-loader”;
SyntaxError: Named export ‘Loader’ not found. The requested module ‘@googlemaps/js-api-loader’ is a CommonJS module, which may not support all module.exports as named exports
The root cause of the issue is that the @googlemaps/js-api-loader package is a CommonJS module, which is not fully supported by the Vite-SSG build process. In particular, the build process is unable to properly handle the named exports from the package, which results in the aforementioned error message.
Troubleshooting with the Lightrun Developer Observability Platform
Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.
-
Explanation of the problem
An error occurred while running a TypeScript project. The error message is:
./node_modules/pdfjs-dist/build/pdf.js 3657:145 Module parse failed: Unexpected token (3657:145) File was processed with these loaders: * ./node_modules/babel-loader/lib/index.js You may need an additional loader to handle the result of these loaders. | numPages: this._numPages, | annotationStorage: (annotationStorage === null || annotationStorage === void 0 ? void 0 : annotationStorage.getAll()) || null, > filename: ((_this$_fullReader = this._fullReader) === null || _this$_fullReader === void 0 ? void 0 : _this$_fullReader.filename) ?? null | }).finally(() => { | if (annotationStorage) {The error occurs in a TypeScript project, but the same code works fine in a React JS project. The relevant portions of
tsconfig.jsonandpackage.jsonare included in the description. The TypeScript configuration is set to target ES5 and uses a number of language features such asesnextandjsx. The project has a number of dependencies includingreact,react-dom, andtypescript.Troubleshooting with the Lightrun Developer Observability Platform
Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.- Instantly add logs to, set metrics in, and take snapshots of live applications
- Insights delivered straight to your IDE or CLI
- Works where you do: dev, QA, staging, CI/CD, and production
Start for free today
Problem solution for babel-loader You may need an additional loader to handle the result of these loaders in ansu5555 pdf-viewer-reactjs
The root cause of the problem is that the version of the “pdfjs-dist” package specified in the project’s dependencies uses a caret (^) before the version number. This is a common practice when specifying package versions in npm and it allows npm to install the most recent version of the package that is compatible with the version specified. For example, if the package.json file has the following dependency:
"dependencies": { "pdfjs-dist": "^2.6.347" }When running
npm install, npm will install the most recent version of “pdfjs-dist” that is compatible with version 2.6.347, which could be a version greater than 2.6.347. This can cause issues if the new version is not compatible with the current project.To solve this problem, the user can use the “npm-force-resolutions” package. This package allows to specify which versions of packages should be used during installation, regardless of the versions specified in the dependencies.
"resolutions": { "pdfjs-dist": "2.6.347" }This will force npm to install version 2.6.347 of “pdfjs-dist” and not the most recent compatible version.
To make sure that the specified version of the package is used during installation, the user should add a “preinstall” script in package.json, which will run “npm-force-resolutions” before running the npm install command.
"scripts": { "preinstall": "npx npm-force-resolutions", ... }This way, when running
npm install, it will first run “npm-force-resolutions” and ensure that the specified version of “pdfjs-dist” is installed. This should resolve the issue of the incompatible version of the package causing an error.Other popular problems with pdf-viewer-reactjs
Problem: PDF viewer not rendering in production environment.
When building and deploying a React application that uses the “pdf-viewer-reactjs” package, the PDF viewer may not render correctly in the production environment. This issue is often caused by webpack not correctly handling the file paths of the PDF.js library that is included with the “pdf-viewer-reactjs” package.
Solution:
To fix this issue, the user can use the “copy-webpack-plugin” to copy the PDF.js library from the “pdf-viewer-reactjs” package to the build folder during the webpack build process.
const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { // ... plugins: [ new CopyWebpackPlugin([ { from: 'node_modules/pdfjs-dist/build/pdf.js', to: 'pdf.js' }, ]), // ... ], // ... };Problem: Error “Module not found: Error: Can’t resolve ‘fs’” when running the application
When running the application that uses the “pdf-viewer-reactjs” package, an error may occur saying “Module not found: Error: Can’t resolve ‘fs’”. This is because the PDF.js library that is included with the “pdf-viewer-reactjs” package relies on the Node.js “fs” module, which is not available in the browser.
Solution:
To fix this issue, the user can use the “fs-webpack-plugin” to replace the Node.js “fs” module with a browser-compatible version during the webpack build process.
const FsWebpackPlugin = require('fs-webpack-plugin'); module.exports = { // ... plugins: [ new FsWebpackPlugin(), // ... ], // ... };Problem: Error “TypeError: Cannot read property ‘getDocument’ of undefined” when rendering the PDF viewer component
When rendering the PDF viewer component provided by the “pdf-viewer-reactjs” package, an error may occur saying “TypeError: Cannot read property ‘getDocument’ of undefined”. This is caused by the PDF.js library not being properly initialized before the component is rendered.
Solution:
To fix this issue, the user can use the “pdfjs-dist” package to initialize the PDF.js library before the component is rendered.
import pdfjs from 'pdfjs-dist'; pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; function App() { return ( <div className="App"> <PdfViewer pdfUrl="example.pdf" /> </div> ); } export default App;It is important to note that the version of pdfjs passed to the workerSrc should match the version of pdfjs-dist that you are using.
A brief introduction to pdf-viewer-reactjs
pdf-viewer-reactjs is a React-based library for displaying PDF documents in web applications. It is built on top of the PDF.js library, which is a JavaScript library for rendering PDF documents in web browsers. pdf-viewer-reactjs provides a set of React components that wrap the functionality provided by PDF.js, making it easy to integrate PDF viewing capabilities into React-based web applications.
The main component provided by pdf-viewer-reactjs is the PdfViewer component, which is a React component that renders a PDF document in a web page. The PdfViewer component can be configured to display the PDF in different ways, such as in a single page or in a continuous scrolling mode. It also provides various other functionalities like displaying thumbnails, searching for text, etc. Additionally, it also allows for annotations and form filling, which makes it very useful for business and legal documents. The library is highly customizable and can be tailored to specific needs of the project. It is also compatible with most modern browsers and has a small footprint, which makes it a great choice for web-based PDF viewing applications.
Most popular use cases for pdf-viewer-reactjs
- Displaying PDF documents in web applications: pdf-viewer-reactjs can be used to display PDF documents within a web application. The library provides a React component that can be integrated into the application to display the PDF document. This can be useful for web-based document management systems, legal document management, and other applications that need to display PDF documents to users.
import { PdfViewer } from 'pdf-viewer-reactjs'; function App() { return ( <div className="App"> <PdfViewer pdfUrl="example.pdf" /> </div> ); } export default App; - Annotation and form filling: pdf-viewer-reactjs provides annotation and form filling functionality, which can be used to add comments, highlights, and other annotations to PDF documents. This can be useful for business and legal documents where users need to add comments and annotations to the document before signing or submitting it.
- Searching for text within the PDF: pdf-viewer-reactjs provides a built-in search feature that allows users to search for specific text within a PDF document. This can be useful for large documents where users need to quickly find specific information. The library provides a search bar component that can be integrated into the application to allow users to search for text within the PDF document.
- Insights delivered straight to your IDE or CLI
- Works where you do: dev, QA, staging, CI/CD, and production
Start for free today
Problem solution for Error in build: Named export. The requested module is a CommonJS module in antfu Vite SSG
The problem at hand is that the build is failing when using the @googlemaps/js-api-loader package. The code works in development mode but not in production. The error message that is displayed is “SyntaxError: Named export ‘Loader’ not found.”. This error is caused by the fact that the requested module, @googlemaps/js-api-loader, is a CommonJS module, which may not support all the module.exports as named exports.
The solution to this issue is to use a bundler such as webpack or rollup that can handle both CommonJS and ES modules, to convert the CommonJS modules to ESM. This can be done by using a plugin such as commonjs-esm-bundler.
Here is an example of how to use the commonjs-esm-bundler plugin in a webpack config file:
const commonjs = require('commonjs-esm-bundler');
module.exports = {
//...
module: {
rules: [
{
test: /.mjs$/,
use: [
{
loader: commonjs.bundle
}
]
}
]
}
};
Additionally, You can install the es-module-shims package to use the Loader package as an ES6 module, in this case, you can change your imports to
import Loader from '@googlemaps/js-api-loader/dist/es-module/Loader.mjs';
It is also worth noting that it is a best practice to check the documentation of the package you are trying to use to see if it provides an ESM or a CJS module, and if it does not, to check if there is a recommended way to use the package in an ESM environment.
Other popular problems with antfu Vite SSG
Problem: Error in Build: Named export ‘Loader’ not found
When using the package @googlemaps/js-api-loader in an antfu Vite SSG project, the build may fail with the error “Named export ‘Loader’ not found”. This issue occurs because the requested module ‘@googlemaps/js-api-loader’ is a CommonJS module, which may not support all module.exports as named exports.
Solution:
To solve this issue, one solution is to convert the CommonJS module to an ES module by adding the following line at the top of the file where the package is imported:
import '@googlemaps/js-api-loader/dist/esm/index.js'
Another solution is to use a tool like es-module-shims to allow the CommonJS module to be used as an ES module.
Problem: Error in Build: SyntaxError: ‘import’ and ‘export’ may appear only with ‘sourceType: module’
When using the antfu Vite SSG template, the build may fail with the error “SyntaxError: ‘import’ and ‘export’ may appear only with ‘sourceType: module’”. This issue occurs because the project is not configured to use ES modules, and the template is trying to use the import and export syntax.
Solution:
To solve this issue, one solution is to update the project’s configuration to use ES modules. This can be done by adding the following to the project’s .babelrc file:
{
"presets": [
["@babel/preset-env", { "modules": false }]
]
}
Another solution is to change the import and export statement to commonjs style statement.
Problem: Error in internal: An internal error occurred.
When using the antfu Vite SSG, an internal error may occur. This issue can be caused by a variety of reasons, such as a bug in the Vite SSG package or a problem with the project’s configuration.
Solution:
To solve this issue, one solution is to check the Vite SSG GitHub repository for any known issues and solutions. Another solution is to check the project’s configuration and ensure that it is set up correctly. If the problem persists, it is recommended to report the issue on the Vite SSG GitHub repository for further assistance.
A brief introduction to antfu Vite SSG
antfu Vite SSG is a static site generator built on top of the Vite development server. It allows for the creation of fast, statically generated sites with the convenience of a development server. The Vite SSG uses the Vite development server to provide a development experience with hot-module replacement, which allows for instant updates in the browser without the need for a full page reload. Additionally, it uses the Vite plugin system to enable features such as static site generation and server-side rendering.
One of the key features of antfu Vite SSG is its support for Vue.js. It allows developers to use Vue’s component-based structure and reactivity system to build performant, dynamic websites. The Vite SSG also supports JSX and TypeScript, making it possible to use a variety of modern front-end development tools and languages. Additionally, it is built on top of the Vite development server, which provides a fast and efficient development experience, with features such as hot-module replacement and a lightweight dev server.
Most popular use cases for antfu Vite SSG
- Building high performance and lightweight static websites: antfu Vite SSG is a framework that allows developers to build and deploy static websites with lightning fast performance. It uses a native ES modules based development setup, which allows for faster development and build times compared to traditional bundlers.
- Serverless deployment: antfu Vite SSG is designed to work seamlessly with serverless platforms, such as Vercel, AWS Lambda, and Firebase, allowing for easy and cost-effective deployment of static websites.
- Dynamic content generation: antfu Vite SSG’s support for dynamic imports and dynamic routes enables the generation of dynamic content, such as pages and posts, at build time. This can be achieved by using a code block like this:
import { createSSG } from 'vite-ssg'
const routes = [
'/about',
'/blog/:slug'
]
export const generate = createSSG(routes, async ({ route, setData }) => {
if (route.path === '/about') {
setData({ title: 'About me' })
} else if (route.path.startsWith('/blog/')) {
const post = await getPostBySlug(route.params.slug)
setData({ title: post.title })
}
})
This code block shows how to create dynamic routes for the website and setData for the routes. This allows for dynamic content to be generated at build time, which can be useful for building blogs and other dynamic pages.