mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.07k stars 2.21k forks source link

Add webpack support #1649

Closed twelch closed 8 years ago

twelch commented 8 years ago

I'm able to bundle gl-js using webpack, but I'm getting a runtime error (in glify) with Chrome 46 on OSX. @tmcw mentioned this has been reported before and that a webpack alternative to glify may be needed. Adding an issue for reference and noting workaround.

Uncaught TypeError: Cannot read property 'match' of undefined

at https://github.com/mapbox/glify/blob/master/index.js#L13

Simple example showing my work -- https://github.com/twelch/react-mapbox-gl-js/tree/webpack-test One workaround is to shim with the pre-built gl-js library using the webpack script-loader module.

require("script!mapbox-gl/dist/mapbox-gl.js");

instead of

import mapboxgl from 'mapbox-gl';
tmcw commented 8 years ago

My PR at https://github.com/mapbox/glify/pull/7 avoids the browserify check, and combined with a section in the webpack config like

{
  node: {
   fs: "empty"
  }
}

(people recommend this but nobody knows what it does)

That said, that only gets us to the point where it appears that the transform doesn't work. Hands-on testing and development of this compatibility layer might be better left to someone with more knowledge of webpack internals.

Madumo commented 8 years ago

I putted an alias in my webpack config: 'mapbox-gl': path.resolve('./node_modules/mapbox-gl/dist/mapbox-gl.js') so i can still use the es6 module syntax. But it would be great if the lib could be bundled by webpack.

hannesj commented 8 years ago

It is not just the glify that is the problem. I tried manually compiling the shaders and using the result to build with webpack but it still fails, as dispatcher.js uses webworkify to generate the worker files/blobs with browserify. I tried to change those to webpack's worker-loader but failed in getting that to work.

yuvadm commented 8 years ago

Curious how far we are on getting gl-js + react + webpack to work. Is this a problem that requires a long term architectural-level solution?

lucaswoj commented 8 years ago

@hannesj Could you elaborate on why webpack's worker-loader didn't work?

I tried to change those to webpack's worker-loader but failed in getting that to work.

hannesj commented 8 years ago

@lucaswoj, Sorry, I didn't debug it very thoroughly, as it works to just bundle in the pre-packaged js. It seemed that the individual workers were spun up correctly, but for some reason the event listeners in the worker didn't get executed when messages were sent from the main thread.

yuvadm commented 8 years ago

@hannesj can you explain a bit more about your solution? Did you just use a prebundled shim same way as in https://github.com/twelch/react-mapbox-gl-seed/blob/master/src/components/GLMap.js#L3-L4 ?

hannesj commented 8 years ago

@yuvadm, basically yes, except that we don't use the script-loader as mapbox-gl is exposed ad a commonJS module. You can see our usage here

yuvadm commented 8 years ago

Permalink for @hannesj previous link: https://github.com/HSLdevcom/digitransit-ui/blob/8fab2aa06f96715832d45ddc76e34c168fa1d178/app/component/map/navigation-map.cjsx#L17

TheBubbleDuck commented 8 years ago

Even if you are building with webpack (I have been doing so), minifyify is also a regular dep. Because it is a regular dep, it has a peerDep of Browserify. That might also cause some issues at some point (npm shrinkwrap issue for us).

cezary commented 8 years ago

I was running into problems bundling mapbox-gl-js into a webpack package (ridiculously long production build times when using dist/mapbox-gl-dev, dist/mapbox-gl not working), so I made a webpack-compatible branch.

The main changes were using loaders to package the shaders and worker files. Documentation generation no longer works because of non-js dependencies.

jingsam commented 8 years ago

Is there any progress to support webpack?

lucaswoj commented 8 years ago

Any progress updates will be posted to this ticket. We would be thrilled to review a PR adding Webpack support by someone who uses and understands the platform.

jingsam commented 8 years ago

I found a blog about it. https://mikewilliamson.wordpress.com/2016/02/24/using-mapbox-gl-and-webpack-together/

It just works. Thx Mike Williamson

DenisCarriere commented 8 years ago

Thanks @sleepycat (Mike) for making this blog post!

bensleveritt commented 8 years ago

@misterfresh This is very helpful.

Might want to consider setting up a way to inform users of your lib when/if your lib becomes deprecated.

eltoro commented 8 years ago

This finally worked for me for anyone using react 0.15, map box-gl-js 0.17 and ES6 import:

npm install brfs, json-loader, transform-loader, webworkify-webpack -S

inside webpack.config.js

resolve: {
    alias: {
      webworkify: 'webworkify-webpack'
    }
 },
module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'react-hot!babel',
        exclude: /node_modules/,
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      }
    ],
    postLoaders: [
      {
        include: /node_modules\/mapbox-gl/,
        loader: 'transform',
        query: 'brfs'
      }
    ]
  }
DenisCarriere commented 8 years ago

@eltoro I'm pretty sure this is a typo son-loader should be >> json-loader

eltoro commented 8 years ago

Yep, thanks. I also added the resolve alias for webworkify-webpack. Without it the styles don't work. I can confirm that this setup is working for me.

DenisCarriere commented 8 years ago

@eltoro Still having issues when using mapbox-gl 0.18.0.

Google Chrome Runtime Error

use_program.js?6fd0:11Uncaught TypeError: fs.readFileSync is not a function

I've fixed it by adding another loader for use_program.js.

loaders: [
  {
    test: /\.js$/,
    include: path.resolve(__dirname, 'node_modules/mapbox-gl/js/render/painter/use_program.js'),
    loader: 'transform/cacheable?brfs'
  }
...
kislovskij commented 8 years ago

In my case webpack had trouble to resolve to mapboxgl using mapbox-gl 0.18.0. I changed the import statement and now it works.

import * as mapboxgl from 'mapbox-gl';

Also I added a post loader in my webpack config.

postLoaders: [ { include: /node_modules\/mapbox-gl/, loader: 'transform', query: 'brfs' } ]

leontyr commented 8 years ago

Tried everything suggested but still getting the Cannot find module 'mapbox-gl' error. Could anyone please help?

import * as mapboxgl from 'mapbox-gl';

webpack.config.js

var path = require('path');
var webpack = require('webpack');
var merge = require('extendify')({
    isDeep: true,
    arrays: 'concat'
});
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCSS = new ExtractTextPlugin('styles.css');
var devConfig = require('./webpack.config.dev');
var prodConfig = require('./webpack.config.prod');
var isDevelopment = process.env.ASPNET_ENV === 'Development';

module.exports = merge({
    resolve: {
        extensions: ['', '.js', '.ts'],
        alias: {
            webworkify: 'webworkify-webpack'
        }
    },
    module: {
        loaders: [{
            test: /\.ts$/,
            include: /ClientApp/,
            loader: 'ts-loader'
        }, {
            test: /\.html$/,
            loader: 'raw-loader'
        }, {
            test: /\.css/,
            loader: extractCSS.extract(['css'])
        }, {
            test: /\.json$/,
            loader: 'json-loader'
        }, {
            test: /\.js$/,
            include: path.resolve(__dirname, 'node_modules/mapbox-gl/js/render/painter/use_program.js'),
            loader: 'transform/cacheable?brfs'
        }, {
            test: /\.js$/,
            include: path.resolve(__dirname, 'node_modules/webworkify/index.js'),
            loader: 'worker'
        }],
        postLoaders: [{
            include: /node_modules\/mapbox-gl/,
            loader: 'transform',
            query: 'brfs'
        }]
    },
    entry: {
        main: ['./ClientApp/boot-client.ts']
    },
    output: {
        path: path.join(__dirname, 'wwwroot', 'dist'),
        filename: '[name].js',
        publicPath: '/dist/'
    },
    plugins: [
        extractCSS,
        new webpack.DllReferencePlugin({
            context: __dirname,
            manifest: require('./wwwroot/dist/vendor-manifest.json')
        })
    ]
}, isDevelopment ? devConfig : prodConfig);
leontyr commented 8 years ago

I've figured out the problem. It's that I'm using Typescript and mapbox-gl doesn't support it...

aidanlister commented 8 years ago

I can't get this working either, I've got the "fs" set to "empty" and the postLoaders ... I'm getting Uncaught TypeError: Cannot convert undefined or null to object

In this chunk of mapbox code:

    var stringify = JSON.stringify;

    module.exports = function (fn) {
        var keys = [];
        var wkey;
        var cacheKeys = Object.keys(cache);

        for (var i = 0, l = cacheKeys.length; i < l; i++) {
            var key = cacheKeys[i];
            var exp = cache[key].exports;
tmcw commented 8 years ago

Dear subscribed - I think I've crafted a webpack configuration / documentation for how you need to tweak webpack configuration that will work. This is more or less a subset of everyone else's configurations here. I've tested it with v0.18.0 and it works correctly. Can you confirm or report specific errors, and then we'll get this integrated into our documentation so we can close this issue out?

https://gist.github.com/tmcw/405086f853560f8a017fefdcb949cb49

leontyr commented 8 years ago

I also need to add the following for it to work.

node: {
    fs: "empty"
},

The problem for me now is that it only works (map showing) in the entry file of the webpack.config.js. It might due to the other settings in my project. Am I the only one having this problem?

tmcw commented 8 years ago

@leontyr do you have the transform loader configured to use brfs? This configuration works without fs: empty for me, I'd assume because it's correctly using brfs. This is with webpack 1.13.0 and Mapbox GL JS 0.18.0

leontyr commented 8 years ago

My bad. You are right, it doesn't need it. It's my other settings messed it up.

I am trying to import mapbox-gl into a project generated by yeoman generator-aspnetcore-spa but can't get it to work properly...

tsemerad commented 8 years ago

I'm getting cannot resolve module 'gl' after adding the settings laid out in the example webpack config. Would this error be caused by the postLoaders entry not working, or the 'transform/cacheable?brfs' loader not working? I updated the path to point to the proper location of use_program.js. I'm using Mapbox GL JS 0.18.0 and webpack 1.13.1.

shanecav commented 8 years ago

@tsemerad I'm also using Mapbox GL JS 0.18.0 and webpack 1.13.1, but I am not having any issues building with webpack. Here's my webpack.config (only the relevant parts):

module.exports = {
  resolve: {
    alias: {
      'webworkify': 'webworkify-webpack'
    }
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loaders: ['babel'],
        exclude: /node_modules/,
        include: __dirname
      },
      {
        test: /\.json$/,
        loaders: ['json']
      },
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'node_modules/mapbox-gl/js/render/painter/use_program.js'),
        loaders: ['transform/cacheable?brfs']
      }
    ],
    postLoaders: [
      {
        include: /node_modules\/mapbox-gl/,
        loader: 'transform',
        query: 'brfs'
      }
    ]
  },
}
djbyrd commented 8 years ago

@leontyr There is a typed definition for mapbox-gl.js called typed-mapbox-gl

primozs commented 8 years ago

The published webpack config works but problem might be with the last version of webworkify-webpack. I had to downgrade from "webworkify-webpack": "1.1.0" to "webworkify-webpack": "1.0.6" to make it work again.

tsemerad commented 8 years ago

I solved the Cannot resolve module 'gl' issue. It turns out my webpack config was adding mapbox-gl to externals. Updating my externals to just a few explicit packages (rather than a function that was auto-generating a list of packages to add to externals) fixed it. Sorry for the confusion.

infacq commented 8 years ago

if anyone can help me with this problem, I post a question here http://stackoverflow.com/questions/37608118/uncaught-typeerror-fs-readfilesync-is-not-a-function

zhuang-hao-ming commented 8 years ago

i have tried all of the solutions above but not one works. i got the result fs.readFileSync is not a function and

ERROR in ./~/.npminstall/mapbox-gl/0.18.0/mapbox-gl/js/render/painter/use_program.js
Module not found: Error: Cannot resolve module 'fs' in E:\test\05_18\map\bobomap\trunk\public\mapbox_textst_1\node_modules\.npminstall\mapbox-gl\0.18.0\mapbox-gl\js\render\painter
 @ ./~/.npminstall/mapbox-gl/0.18.0/mapbox-gl/js/render/painter/use_program.js 3:9-22

in the end. can any one help me ?

my webpack.config.js shows that

module.exports = {    
    entry: './main.js',
    output: {
        path: './',
        filename: 'bundle.js',
    },
    resolve: {
        alias: {
            'webworkify': 'webworkify-webpack'
        }
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: 'json-loader'
        }, {
            test: /\.js$/,
            include: path.resolve(__dirname, 'node_modules/mapbox-gl/js/render/painter/use_program.js'),
            loader: 'transform/cacheable?brfs'
        }],
        postLoaders: [{
            include: /node_modules\/mapbox-gl/,
            loader: 'transform',
            query: 'brfs'
        }]
    }
}

and my package.json shows that

{
  "dependencies": {
    "brfs": "^1.4.3",
    "json-loader": "^0.5.4",
    "mapbox-gl": "0.18.0",
    "transform-loader": "^0.2.3",
    "webpack": "1.13.1",
    "webworkify-webpack": "1.0.6"
  }
}

thanks

jingsam commented 8 years ago

Add this:

node: {
    console: true,
    fs: 'empty'
  }
zhuang-hao-ming commented 8 years ago

@jingsam if i add the code snippet you supply , a error fs.readFileSync is not a function shown in the browser console

infacq commented 8 years ago

it also happen to me

KendallPark commented 8 years ago

I am in the same boat as @zhuang-hao-ming and @infacq.

jingsam commented 8 years ago

Webpack example was updated, check out this: https://github.com/mapbox/mapbox-gl-js/blob/master/webpack.config.example.js

yuvadm commented 8 years ago

Things were working well for me, but after purging my node_modules directory and reinstalling all my dependencies (welcome to JS), I'm now getting this error https://github.com/borisirota/webworkify-webpack/issues/10

dnlsandiego commented 8 years ago

@primozs Do you mind sharing the reason why downgrading "webworkify-webpack" to 1.0.6 worked with the published webpack config? I ran into the same issue and your comment fixed it. Maybe so it could be noted in the published webpack guide and config.

primozs commented 8 years ago

Hi @dnlsandiego, I did not go and check what was new, for now I just stayed at 1.0.6 Cheers

dvreed77 commented 8 years ago

I am having a little bit of a different issue. I have a webpack-mapboxgl implementation that compiles and works, but there are HUGE blobs that are being generated and downloaded directly related to the number of maps I am creating. Example is here: http://test.dvreed.com/fhr/. I have 5 maps, and there are 15 huge blobs that are downloaded. They are each the same exact size at about 1MB, which match the size of the bundle.js. Any help would be greatly appreciated.

->webpack --config webpack-production.config.js -p
Hash: b80ca238b8521f64996f
Version: webpack 1.13.1
Time: 49332ms
        Asset     Size  Chunks             Chunk Names
    bundle.js  1.11 MB       0  [emitted]  main
bundle.js.map  9.15 MB       0  [emitted]  main
   [0] multi main 28 bytes {0} [built]
    + 896 hidden modules

Here is my production version of my webpack config

// TO RUN:
// export NODE_ENV=production
// webpack --config webpack-production.config.js -p

var path = require('path');
var webpack = require('webpack');

module.exports = {
  devtool: 'source-map',
  entry: [
    './index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      }
    })
  ],
  resolve: {
    alias: {
      'webworkify': 'webworkify-webpack'
    }
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loaders: [ 'babel' ],
        exclude: /node_modules/,
        include: __dirname
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.js$/,
        include: path.resolve('node_modules/mapbox-gl-shaders/index.js'),
        loader: 'transform/cacheable?brfs'
      }
    ],
    postLoaders: [{
      include: /node_modules\/mapbox-gl-shaders/,
      loader: 'transform',
      query: 'brfs'
    }]
  }
};
mike-marcacci commented 8 years ago

I've been meaning to post this here for a couple weeks now, but for anyone who forgot to shrinkwrap your deps or is adding mapbox-gl-js to a new project, the webworkify-webpack project has made some recent changes that break mapbox somehow (and like most people didn't actually follow semver).

I haven't had a chance to dive in yet, but can say that mapbox continues to work in webpack using webworkify-webpack version 1.0.6, but fails in 1.1.x.

bensleveritt commented 8 years ago

@mike-marcacci I've actually found webworkify-webpack@1.1.3 still works, but I too haven't had a chance to really delve into the details of why it stopped working.

This is the issue I raised here: https://github.com/mapbox/mapbox-gl-js/issues/2933 but ultimately it's probably more a webworkify-webpack issue.

ReLrO commented 8 years ago

@dvreed77 This happens to me as well. I have similar settings to yours. Any luck finding the solution?

dvreed77 commented 8 years ago

@ReLrO No, I ended up using standard mapbox.js and everything works great now. Mapbox GL was a little overkill for what I was trying to do, so it didn't bother me too much.

ReLrO commented 8 years ago

@dvreed77 Ok thanks. I might take a look at it as well then. Do you think the problem is with Mapbox GL or with webpack?

dvreed77 commented 8 years ago

@ReLrO Not enough of an expert in either to say, sorry. I think it might just be a config mistake I have.