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';
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.
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.
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.
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?
@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.
@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.
@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 ?
@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
Permalink for @hannesj previous link: https://github.com/HSLdevcom/digitransit-ui/blob/8fab2aa06f96715832d45ddc76e34c168fa1d178/app/component/map/navigation-map.cjsx#L17
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).
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.
Is there any progress to support webpack?
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.
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
Thanks @sleepycat (Mike) for making this blog post!
@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.
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'
}
]
}
@eltoro I'm pretty sure this is a typo son-loader
should be >> json-loader
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.
@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'
}
...
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'
}
]
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);
I've figured out the problem. It's that I'm using Typescript and mapbox-gl doesn't support it...
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;
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
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?
@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
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...
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.
@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'
}
]
},
}
@leontyr There is a typed definition for mapbox-gl.js called typed-mapbox-gl
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.
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.
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
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
Add this:
node: {
console: true,
fs: 'empty'
}
@jingsam if i add the code snippet you supply , a error fs.readFileSync is not a function
shown in the browser console
it also happen to me
I am in the same boat as @zhuang-hao-ming and @infacq.
Webpack example was updated, check out this: https://github.com/mapbox/mapbox-gl-js/blob/master/webpack.config.example.js
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
@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.
Hi @dnlsandiego,
I did not go and check what was new, for now I just stayed at 1.0.6
Cheers
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'
}]
}
};
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
.
@mike-marcacci I've actually found [email protected]
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.
@dvreed77 This happens to me as well. I have similar settings to yours. Any luck finding the solution?
@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.
@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?
@ReLrO Not enough of an expert in either to say, sorry. I think it might just be a config mistake I have.
@dvreed77 I found a solution to the bug if you are interested. There is a memory leak in mabox-gl and its connection with webworkify. My solution involves modifying code both in mapbox-gl and in webworkify-webpack.
Basically in webworkify-webpack you need to change the last lines of index.js to:
var objectUrl = URL.createObjectURL(
new Blob([src], { type: 'text/javascript' })
);
var w = new Worker(objectUrl);
w.objectUrl = objectUrl;
return w;
Then in mapbox-gl/js/util/actor.js add
this.first = true;
to the Actor constructor (lines 15 - 22) and in Actor.prototype.receive function add the following lines:
if (this.first) {
// revoke the Object URL that was used to create this worker, so as
// not to leak it
URL.revokeObjectURL(this.target.objectUrl);
this.first = false;
}
This removes the blob instead of keeping it in memory, which causes a memory leak.
I also added this line:
this.actors[i].target.removeEventListener('message', this.actors[i].receive);
to the for loop in the remove function in mapbox-gl/js/util/dispatcher.js
to ensure the event listener is also removed once the map is removed.
Hope this helps.
@ReLrO Wow, great find! Does anyone else know of this memory leak? Should definitely do a pull a request in this case
@dvreed77 I thought of it, but the fix depends on the modification of webworkify-webpack and until webworkify-webpack will change, the fix for mapbox-gl-js wont work...
Weird error happening over here. Everything compiles just fine and is working great in all environments (Recent versions of Chrome + Firefox + Safari tested) EXCEPT for Safari v.8.0 (tested on 8.0.8 on desktop + iOS 8). When running on Safari v.8.x, the following error is surfaced:
[Error] Error: webworkify-webpack: Could not locate module containing worker function! Make sure you aren't using eval sourcemaps and that you pass named functions to webworkify-webpack!
_stacktrace_
perform (core.js, line 5)
batchedUpdates (core.js, line 5)
s (core.js, line 5)
r (core.js, line 5)
enqueueCallback (core.js, line 5)
setState (core.js, line 5)
(anonymous function) (2.6aa3fec414b8cd3371d7.bundle.js, line 9)
(anonymous function) ([native code], line 0)
s (core.js, line 2)
fireWith (core.js, line 2)
r (core.js, line 3)
(anonymous function) (core.js, line 3)
UPDATE 1 When running the webpack build without uglify, the problem disappears. Investigating further now.
in other browsers (this time chrome 34.0.1847.116) getting a different runtime error. Here's a better stacktrace from an un-minified bundle:
Uncaught TypeError: undefined is not a function
5.chunk.js:27473
module.exports 5.chunk.js:27473
module.exports 5.chunk.js:27384
Dispatcher 5.chunk.js:27244
Style 5.chunk.js:17050
util.extend.setStyle 5.chunk.js:14942
module.exports 5.chunk.js:14503
VenueMapMapbox.createMap
some of the above lines:
// find the first moduleId from the above list that contains fnString
27473: var key = potentialFnModuleIds.find(function (moduleId) {
27383: module.exports = function () {
27384: return new WebWorkify(__webpack_require__(567));
27385: };
UPDATE After some debugging, i've found the error is occurring because the method find
wasn't added to the Array prototype on Chrome till v.45.
polyfilling the method with the snippet here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find -
solved the issue for me
@aidanlister Hi there, I am facing the same issue, but didn't figure it out. Is yours resolved? Thanks!
Has anyone gotten it to work with Webpack 2? → https://webpack.js.org/configuration/
Here's my non-working configuration
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
...
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'mapbox-gl': resolve('node_modules/mapbox-gl/dist/mapbox-gl.js'),
'webworkify': 'webworkify-webpack'
}
},
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, 'node_modules/mapbox-gl/js/render/painter/use_program.js'),
loader: 'transform/cacheable?brfs'
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /node_modules\/mapbox-gl/,
loader: 'transform',
enforce: 'post',
query: 'brfs'
}
],
}
}
Results in
This dependency was not found:
* mapbox-gl in ./~/babel-loader/lib!./~/vue-loader/lib/selector.js?type=script&index=0!./src/components/Mapbox.vue
Solved it by removing the two loaders (just not in conjunction with UglifyJS, see below)
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
...
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'mapbox-gl': resolve('node_modules/mapbox-gl/dist/mapbox-gl.js'),
'webworkify': 'webworkify-webpack'
}
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
}
],
}
}
However, building it with UglifyJsPlugin
results in Uncaught ReferenceError: n is not defined
for the Mapbox component. Thoughts?
In create-react-app
project
import mapboxgl from 'mapbox-gl';
I'm getting Critical dependencies: 1:481-488 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results. @ ./~/mapbox-gl/dist/mapbox-gl.js 1:481-488
I am using the default webpack configuration that comes with the vuejs project scaffolded using the vue-cli together with the webpack template. Mapbox works perfectly during development but when I build the project mapbox throws this error:
Uncaught ReferenceError: e is not defined
.
My webpack file looks like this
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: "pre",
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
Someone help please
@Paradzayi
Try doing what @zezhipeng mentions here:
https://github.com/mapbox/mapbox-gl-js/issues/4359
module: {
...
noParse: /(mapbox-gl)\.js$/,
...
}
It fixed the exact same problem for me:
@onehorsetown your solution works like charm. Thanks a lot 👍 👏 .
I had come up with a not so elegant work around. I added
module.exports = {
...
externals: {
"mapbox-gl": 'mapboxgl'
}
...
}
to the webpack.config.js
file. I did this to prevent the mapbox-gl
package from being bundled with webpack but I had to require it in the index.html
file using <script>
tags.
I end up doing just adding
module.exports = {
...
node: {
fs: 'empty'
},
module: {
rules: [
{
test: /node_modules.+js$/,
loader: 'ify-loader'
}
]
}
...
}
and it woks using web pack 2.0 you need to add ify-loader npm i -D ify-loader
We are using it with Angular 6 and getting an error. I'm not sure where should I added this. Any idea in which file(probably tsconfig.json) and in which block I should add it?
@mitulgolakiya add angular json => "scripts": ["node_modules/mapbox-gl/dist/mapbox-gl.js"]
Most helpful comment
@aidanlister Hi there, I am facing the same issue, but didn't figure it out. Is yours resolved? Thanks!