Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { defineConfig } from "eslint/config";

export default defineConfig(
{
ignores: ["dist/", "node_modules/", "src/bootstrap.js"],
ignores: ["**/dist/", "**/node_modules/", "src/bootstrap.js"],
},
{
languageOptions: {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
"scripts": {
"prepack": "npm run build",
"lint": "eslint .",
"test": "NODE_OPTIONS='--experimental-vm-modules --disable-warning=ExperimentalWarning' jest ./src",
"test": "npm run lint && npm run test:unit && npm run test:bundlers",
"test:unit": "NODE_OPTIONS='--experimental-vm-modules --disable-warning=ExperimentalWarning' jest ./src",
"test:bundlers": "cd test-bundlers && ./test-all.sh",
"build": "rm -rf ./dist && rollup -c",
"format": "eslint . --fix"
},
Expand Down
10 changes: 1 addition & 9 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,7 @@ export default [
// ESM build
{
input: "src/index.ts",
plugins: [
...basePlugins,
replace({
preventAssignment: true,
values: {
__DEV__: 'process.env.NODE_ENV !== "production"',
},
}),
],
plugins: [...basePlugins],
output: {
file: "dist/index.js",
format: "esm",
Expand Down
5 changes: 3 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ interface APILibraryMap {

type APILibraryName = keyof APILibraryMap;

// The __DEV__ global variable is set by rollup during the build process.
declare const __DEV__: boolean;
// Development mode check - bundlers will replace process.env.NODE_ENV at build time
declare const process: { env: { NODE_ENV?: string } };
const __DEV__ = process.env.NODE_ENV !== 'production';

let setOptionsWasCalled_ = false;

Expand Down
5 changes: 3 additions & 2 deletions src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ export const MSG_SCRIPT_ELEMENT_EXISTS =
"problems using the API. Make sure to remove the script " +
"loading the API.";

// The __DEV__ global variable is set by rollup during the build process.
declare const __DEV__: boolean;
// Development mode check - bundlers will replace process.env.NODE_ENV at build time
declare const process: { env: { NODE_ENV?: string } };
const __DEV__ = process.env.NODE_ENV !== 'production';

export const logError = (message: string) => {
console.error(`[@googlemaps/js-api-loader] ${message}`);
Expand Down
10 changes: 10 additions & 0 deletions test-bundlers/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Dependencies
node_modules/
package-lock.json

# Build outputs
*/dist/
*/build.log

# Tarball
*.tgz
69 changes: 69 additions & 0 deletions test-bundlers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Bundler Integration Tests

This directory contains integration tests to verify that
`@googlemaps/js-api-loader` works correctly with popular JavaScript bundlers
without requiring any configuration from consumers.

The @googlemaps/js-api-loader library has a development-mode (based on
`process.env.NODE_ENV` checks) that toggle detailed warning messages during
development.

The tests in this directory ensure that some of the most popular bundlers
correctly handle the development mode in a default configuration.

1. **Vite** - Correctly replaces `process.env.NODE_ENV` via its built-in
`define` config
2. **Webpack** - Correctly replaces it via DefinePlugin (default behavior)
3. **Rollup** - Works with standard `@rollup/plugin-replace` configuration

The tests verify both modes:

- **Production mode**: `process.env.NODE_ENV` is replaced, dev warnings are
removed
- **Development mode**: `process.env.NODE_ENV` is replaced with `"development"`,
dev warnings are preserved

## Running Tests

```bash
./test-all.sh
```

### Individual bundler:

```bash
cd vite-test
npm install
npm install $(npm pack --silent ../../)
npm run build
```

## What Each Test Does

### Vite (`vite-test/`)

- Uses Vite's zero-config setup
- Relies on Vite's automatic `process.env.NODE_ENV` replacement
- development mode is approximated by disabling minification and building with
`NODE_ENV='development' vite build --mode development`

### Webpack (`webpack-test/`)

- Uses Webpack 5 with minimal config
- Relies on DefinePlugin (enabled by default in production mode)

### Rollup (`rollup-test/`)

- Uses standard Rollup with `@rollup/plugin-replace`
- Represents how users typically configure Rollup

## Expected Output

All tests should pass with:

```
✓ All bundler tests passed!
```

If any test fails, it means the library is shipping code that won't work
correctly in that bundler without additional user configuration.
19 changes: 19 additions & 0 deletions test-bundlers/rollup-test/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "rollup-test",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"build": "rollup -c",
"build:dev": "rollup -c rollup.config.dev.js"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.5",
"@rollup/plugin-terser": "^0.4.4",
"rollup": "^4.6.1"
},
"dependencies": {
"@googlemaps/js-api-loader": "file:../../googlemaps-js-api-loader-2.0.1.tgz"
}
}
20 changes: 20 additions & 0 deletions test-bundlers/rollup-test/rollup.config.dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { nodeResolve } from "@rollup/plugin-node-resolve";
import replace from "@rollup/plugin-replace";

export default {
input: "src/index.js",
output: {
file: "dist/bundle.js",
format: "esm",
},
plugins: [
nodeResolve(),
replace({
preventAssignment: true,
values: {
"process.env.NODE_ENV": JSON.stringify("development"),
},
}),
// Note: No minification in dev mode
],
};
21 changes: 21 additions & 0 deletions test-bundlers/rollup-test/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { nodeResolve } from "@rollup/plugin-node-resolve";
import replace from "@rollup/plugin-replace";
import terser from "@rollup/plugin-terser";

export default {
input: "src/index.js",
output: {
file: "dist/bundle.js",
format: "esm",
},
plugins: [
nodeResolve(),
replace({
preventAssignment: true,
values: {
"process.env.NODE_ENV": JSON.stringify("production"),
},
}),
terser(),
],
};
33 changes: 33 additions & 0 deletions test-bundlers/rollup-test/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { importLibrary, setOptions } from "@googlemaps/js-api-loader";

// Configure the Google Maps API
setOptions({
apiKey: "YOUR_API_KEY",
version: "weekly",
});

// Initialize the map
async function initMap() {
const { Map } = await importLibrary("maps");

return new Map(document.getElementById("map"), {
center: { lat: 37.7749, lng: -122.4194 },
zoom: 12,
});
}

// Load markers
async function addMarkers(map) {
const { AdvancedMarkerElement } = await importLibrary("marker");

const marker = new AdvancedMarkerElement({
position: { lat: 37.7749, lng: -122.4194 },
title: "San Francisco",
});
marker.map = map;
}

// Start the application
initMap()
.then((map) => addMarkers(map))
.catch(console.error);
138 changes: 138 additions & 0 deletions test-bundlers/test-all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/bin/bash

# Test bundler compatibility for @googlemaps/js-api-loader
# This script tests that the library works with various popular bundlers
# without requiring any configuration from the user.

set -e # Exit on any error

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"

echo "======================================"
echo "Testing Bundler Compatibility"
echo "======================================"
echo ""

# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# Pack the library
echo "📦 Packing library..."
cd "$ROOT_DIR"
TARBALL=$(npm pack --silent 2> /dev/null)
echo " created: $TARBALL"
echo ""

for bundler in vite webpack rollup ; do
dir="$SCRIPT_DIR/${bundler}-test"

(
cd $dir
# Install dependencies
echo " Installing dependencies for $bundler..."
npm install --silent
npm install --silent "../../$TARBALL"
)
done

echo ""

# Function to test a bundler in production mode
test_bundler_prod() {
local bundler=$1
local dir="$SCRIPT_DIR/${bundler}-test"

cd "$dir"

echo "Testing $bundler (production)..."

# Run production build
echo " Building (production)..."
if npm run build > build.log 2>&1; then
# Check for process.env.NODE_ENV references in actual code (not in strings/comments)
# We pipe find to xargs to grep through all bundles at once.
# The if condition checks the exit code of grep.
if find dist -name "*.js" -type f -print0 | xargs -0 grep -qE "process\.env\.NODE_ENV|process\.env\\["; then
echo -e " ${RED}✗ NUM_FAILED${NC} - Found process.env.NODE_ENV in bundle code"
return 1
fi

# Verify that importLibrary is still present (not tree-shaken)
if ! find dist -name "*.js" -type f -exec grep -q "importLibrary" {} \;; then
echo -e " ${RED}✗ NUM_FAILED${NC} - importLibrary was incorrectly tree-shaken"
return 1
fi

echo -e " ${GREEN}✓ PASSED${NC} - process.env replaced, bundle optimized"
return 0
else
echo -e " ${RED}✗ NUM_FAILED${NC} - Build error"
echo "~~~~ build log:"
cat build.log
echo "~~~~"

return 1
fi
}

# Function to test a bundler in development mode
test_bundler_dev() {
local bundler=$1
local dir="$SCRIPT_DIR/${bundler}-test"

cd "$dir"

echo "Testing $bundler (development)..."

# Run development build
echo " Building (development)..."
rm -rf dist
if npm run build:dev > build-dev.log 2>&1; then
# Check that dev warning code is present in the bundle
# We look for the actual console.warn message, not just the function definition.
if find dist -name "*.js" -type f -print0 | xargs -0 grep -qE "console\.warn.*@googlemaps/js-api-loader"; then
echo -e " ${GREEN}✓ PASSED${NC} - dev warnings preserved"
return 0
else
echo -e " ${RED}✗ NUM_FAILED${NC} - dev warning code not found (dead code eliminated incorrectly)"
cat build-dev.log
return 1
fi
else
echo -e " ${RED}✗ NUM_FAILED${NC} - Build error"
cat build-dev.log
return 1
fi
}

NUM_FAILED=0

# Production mode tests
echo "========== PRODUCTION MODE =========="

for bundler in vite webpack rollup ; do
echo ""
test_bundler_prod $bundler || NUM_FAILED=$((NUM_FAILED + 1))
done
echo ""

# Development mode tests
echo "========== DEVELOPMENT MODE =========="
for bundler in vite webpack rollup ; do
echo ""
test_bundler_dev $bundler || NUM_FAILED=$((NUM_FAILED + 1))
done
echo ""

# Summary
echo "======================================"
if [ $NUM_FAILED -eq 0 ]; then
echo -e "${GREEN}✓ All bundler tests passed!${NC}"
exit 0
else
echo -e "${RED}✗ $NUM_FAILED bundler test(s) failed${NC}"
exit 1
fi
Loading
Loading