19

I am using Webpack + html-webpack-plugin to build all my static files. The thing is, when I am using it with Google Maps API, it's not working.

I have this code:

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: -34.397, lng: 150.644},
    zoom: 6
  });
  // the other code, irrelevant
}

And a HTML file:

<!doctype html>
<html>
<head>
</head>
<body>
  <div id="map"></div>
  <script async="async" defer="defer"
      src="https://maps.googleapis.com/maps/api/js?key=<token here>&callback=initMap">
    </script>
   <script src="script.js"></script>
</body>
</html>

If I run just this file, everything works fine. But if I run this with, webpack it complaints about 'initMap is not a function'. I've looked inside the output, and it seems like initMap is declared not as global function, but as a function inside a module or something like that, so maybe that's the issue.

How should I use Google Maps API with webpack? I know that I can bundle some libs with my script, such as react, should I do the same? What should be the approach here?

UPD: Here is my webpack.config.js:

/* eslint-disable */
const path = require('path')
const fs = require('fs')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const nodeModules = {}
fs.readdirSync('node_modules')
  .filter(function(x) {
    return ['.bin'].indexOf(x) === -1
  })
  .forEach(function(mod) {
    nodeModules[mod] = 'commonjs ' + mod
  })

const htmlMinifierObj = {
  collapseWhitespace: true,
  removeComments: true
}

module.exports = [
// the first object compiles backend, I didn't post it since it's unrelated
{
 name: 'clientside, output to ./public',
 entry: {
   script: [path.join(__dirname, 'clientside', 'script.js')]
 },
 output: {
   path: path.join(__dirname, 'public'),
   filename: '[name].js'
 },
 module: {
   loaders: [
     {
       test: /\.js$/,
       loader: 'babel',
       query: { presets:['es2015', 'stage-0'] }
     }
   ],
 },
 plugins: [
   //new webpack.optimize.UglifyJsPlugin({minimize: true}),
   new HtmlWebpackPlugin({
     template: 'clientside/index.html',
     inject: 'body',
     chunks: ['script'],
     minify: htmlMinifierObj
   })
 ],
}]

And the output HTML is (I've removed importing script.js from my source file, because it's added by webpack, and turned off the minimization, just for readability):

<!doctype html>
<html>
<head>
</head>
<body>
  <a href="/login/facebook">Login</a>
  <div id="map"></div>
  <script async defer
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCGSgj5Ts10UdapzUnWlr34NS5cuoBj7Wg&callback=initMap">
    </script>
<script type="text/javascript" src="script.js"></script></body>
</html>
geocodezip
  • 158,664
  • 13
  • 220
  • 245
serge1peshcoff
  • 4,342
  • 11
  • 45
  • 76
  • The google maps API doesn't "pack" with webpack you should keep as external source, if fails it's because the script.js is not packed, or you don't use your new packed js. Please show us your webpack config, and your final html file – Danyel Cabello Nov 13 '16 at 15:53
  • @DanyelDarkcloud updated the question – serge1peshcoff Nov 13 '16 at 16:02

1 Answers1

45

In script.js

After your function declaration, add the function to the global scope, like this:

function initMap() {
    // Some stuff
}
window.initMap = initMap;
Danyel Cabello
  • 777
  • 6
  • 7
  • Ive been gnawing at this for two days… running Webpack with Zurb Foundation for Sites and trying in vain to come up with an idea. This saved me. – visyoual Apr 18 '19 at 19:59
  • You saved me from rewriting my JavaScript code after porting it from a vanilla JS setup to a Webpack architecture. THANK YOU. – Mina Nov 28 '20 at 12:43
  • for Typescript users: https://stackoverflow.com/questions/12709074/how-do-you-explicitly-set-a-new-property-on-window-in-typescript – G. Debailly Dec 16 '20 at 10:21