Load AMD modules in ES6 way.

7611
9
Jump to solution
08-05-2016 08:52 AM
EvelynHernandez
Occasional Contributor III


Hello,

I want to ask how to set up the environment to load AMD modules from Arcgis JS Api 4 or 3.17 in a ES6 way.

Cuz i want to use react as a framework.

I have been seeing for some examples but i still dont understand too well how to do it from 0. (I already see some examples that odoenet site gives and nazarewk/dojo-jsx have in github)

I want to use gulp and webpack dev server.

Thanks for all ur help !

1 Solution

Accepted Solutions
TomWayson
Esri Contributor

If the discussion in this GitHub issue helped you resolve the problems you had getting esri modules to load from ES6 code, would you mind making this question as answered?

Thanks! 

View solution in original post

0 Kudos
9 Replies
ReneRubalcava
Frequent Contributor

Here is a sample using React with 4.0beta3, but everything is still pretty much the same.

GitHub - odoe/esrijs4-vm-react: Using ErsiJS 4.0 View Models with React

This is using Gulp, but not Webpack. If you really want to use Webpack, you can check out this repo for the dojo-webpack-loader

GitHub - Nordth/dojo-webpack-loader: Webpack loader for Dojo Toolkit 1.x

I haven't used it, but it might be what you're looking for.

ReneRubalcava
Frequent Contributor

For a little more clarification, you can basically write your JavaScript in ES6, using ES6 modules and more as you normally would. The key is to let the babel transpiler know you want to compile is as AMD modules, rather than commonjs. Other than that small detail, there really isn't much else to it.

EvelynHernandez
Occasional Contributor III

Im going to try them and see.

Ty

0 Kudos
EvelynHernandez
Occasional Contributor III

Rene,

I still dont understand too much how to incorporate some modules that the arcgis js api has.

For example, i want to use the Search that this example shows: ArcGIS API for JavaScript Sandbox 

How i said, im developing a webapp using the following setup:

React JS as framework.

Webpack as server, my config file is the following:

var path = require('path');
module.exports = {
 entry: {
 login: './static/js/bundles/login.js',
 dashboard: './static/js/bundles/dashboard.js'
 },
 output: {
 path: path.join(path.join(__dirname, 'dist'), 'js'),
 filename: '[name].js'
 },
 devServer: {
 inline: true,
 port: 443,
 host: "127.0.0.1"
 },
 module: {
 loaders: [
 {
 test: /\.(js|jsx)$/,
 exclude: /node_modules/,
 loader: 'babel',
 query: {
 presets: ['react', 'es2015', 'stage-2']
 }
 }
 ]
 }
};

gulp as task manager that doest this:

var gulp = require('gulp');
var sass = require('gulp-sass');
var swig = require('gulp-swig');
var notify = require("gulp-notify");

function defaultError(type){
 return function(err){
 console.log(type + ' error : ' + err);
 };
}
function dist(path){
 return './dist/' + path;
}
function realPath(xs){
 return './static/' + xs;
}
var reportError = function (error) {
 notify({
 title: 'Gulp Task Error',
 message: 'Check the console.'
 }).write(error);
console.log(error.toString());
this.emit('end');
}
gulp.task('sass', function(){
 return gulp.src('./static/css/*.scss')
 .pipe(sass({ outputStyle: 'compact' }))
 .on('error', reportError)
 .pipe(gulp.dest(dist('css')))
});
gulp.task('css', function(){
 return gulp.src('./static/css/*.css')
 .pipe(sass({ outputStyle: 'compact' }))
 .on('error', reportError)
 .pipe(gulp.dest(dist('css')))
});
gulp.task('templates', function(){
 return gulp.src(['./*.html','!./base.html'])
 .pipe(swig())
 .pipe(gulp.dest('dist/templates'));
});
gulp.task('libs', function(){
 return gulp.src('./static/js/vendor/*.js')
 .pipe(gulp.dest(dist('js/vendor')));
});
gulp.task('fonts', function(){
 return gulp.src('./static/css/fonts/*.ttf')
 .on('error', reportError)
 .pipe(gulp.dest(dist('css/fonts')))
});
gulp.task('images', function(){
 return gulp.src('./static/css/images/**/*.png')
 .on('error', reportError)
 .pipe(gulp.dest(dist('css/images')))
});
gulp.task('html', function(){
 return gulp.src('*.html')
 .on('error', reportError)
 .pipe(gulp.dest(dist('')))
});
gulp.task('js', function(){
 return gulp.src('./static/js/vendor/**/*.js')
 .on('error', reportError)
 .pipe(gulp.dest(dist('')))
});
gulp.task('watch', function(){
 gulp.watch(['css/**/*.scss'].map(realPath), ['sass']);
 gulp.watch(['*.html'], ['templates']);

});

gulp.task('default', ['sass', 'templates', 'libs','fonts','images','watch', 'css','html']);

And my package.json file contains this.

{
 "name": "myprojectname",
 "version": "1.0.0",
 "description": "For next project.",
 "main": "server.js",
 "scripts": {
 "start": "start npm run dev:server & start npm run gulp",
 "dev:server": "webpack-dev-server",
 "dev:build": "webpack --progress --colors",
 "prod:build": "webpack --optimize-minimize --progress --colors",
 "gulp": "gulp",
 "test": "echo \"Error: no test specified\" && exit 1"
 },
 "repository": {
 "type": "git",
 "url": "..."
 },
 "author": "",
 "license": "ISC",
 "bugs": {
 "url": "..."
 },
 "homepage": "...#readme",
 "dependencies": {
 "highcharts": "~4.2.4",
 "lodash": "~4.15.0",
 "react": "^0.14.7",
 "react-data-grid": "~0.14.18",
 "react-dom": "^0.14.7",
 "griddle-react": "~0.4.1",
 "react-native": "~0.24.1",
 "jspdf": "~1.2.61",
 "jspdf-autotable": "~2.0.25",
 "cookie-handler": "~1.0.1",
 "redux": "~3.5.2",
 "react-select": "~1.0.0-beta13",
 "rutjs": "~0.1.1",
 "react-image-gallery": "~0.6.4",
 "babel-plugin-transform-decorators-legacy": "~1.3.4",
 "validator": "~5.5.0",
 "react-bootstrap-modal": "~2.1.0",
 "react-modal": "~1.4.0"
 },
 "devDependencies": {
 "babel-core": "^6.6.5",
 "babel-loader": "^6.2.4",
 "babel-preset-es2015": "^6.6.0",
 "babel-preset-react": "^6.5.0",
 "babel-preset-stage-2": "^6.5.0",
 "babelify": "^7.2.0",
 "browserify": "^13.0.0",
 "gulp": "^3.9.1",
 "gulp-notify": "~2.2.0",
 "gulp-sass": "^2.2.0",
 "gulp-swig": "^0.8.0",
 "node-sass": "^3.4.2",
 "react-tabs": "^0.5.3",
 "webpack": "^1.12.14",
 "webpack-dev-server": "^1.14.1",
 "react-bootstrap": "~0.30.0"
 }
}

In the module that im working i want to load the arcgis api features like search, map like this: 

import Search from 'esri/dijit/Search'

The way im doing it now is using the legacy code for all of the developing im working.

For example when i implement Dynamic layers i need to write in this way (and it works).

var layerD = new esri.layers.ArcGISDynamicMapServiceLayer(layers.read_direccionesDyn(),{id:"factigis_d"});
layerD .setImageFormat("png32");
layerD .setVisibleLayers([0]);
mapp.addLayer(layerD );

But for example when i want to write the legacy code for the Search showed in the example,

var search = new esri.dijit.Search({map: mapp}, "search");
search.startup();

it gives me an error saying "Uncaught TypeError: esri.dijit.Search is not a constructor".

If i put:  dojo.require(esri.dijit.Search) is says "multiple define".

Im pretty new on developing in this way , and I have been reading all the guides u guys gave me but im still very confused on how to fix my problem loading the esri modules with the setup that i have.

My html is this one: and there i show where i put the arcgis js api

<html lang="es">
 <head>
 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" >
 <link rel="shortcut icon" href="">
 <title>GISRED - FactiGIS FRONTOFFICE</title>
 <link rel="stylesheet" type="text/css" href="arcgis_js_api/library/3.16/3.16/dijit/themes/tundra/tundra.css" />
 <link rel="stylesheet" type="text/css" href="arcgis_js_api/library/3.16/3.16/esri/css/esri.css" />
 <link rel="stylesheet" href="static/js/vendor/bootstrap.min.css" />
 <link rel="stylesheet" href="static/js/vendor/font-awesome/css/font-awesome.min.css" />
 <link rel="stylesheet" type="text/css" href="dist/css/factigis.css" />
 <script src="static/js/vendor/jspdf/jspdf.min.js"></script>
 <script src="static/js/vendor/jspdf/jspdf.plugin.autotable.js"></script>
 <script src="static/js/vendor/jspdf/faker.min.js"></script>
 <link rel="stylesheet" href="dist/css/react-select.css">
</head>
 <body class="bodyfactigis">
 <div id="myFactigis_FrontOffice" class="myFactigis_FrontOffice"></div>
 <script type="text/javascript" src="arcgis_js_api/library/3.16/3.16/init.js"></script>
 <script src="static/js/vendor/jquery.min.js"></script>
 <script src="static/js/vendor/lodash.core.js"></script>
 <script src="static/js/vendor/jQueryRotate.js"></script>
 <script src="factigisFrontoffice.js"></script>
</body>
</html>

I hope u guys that understand more than me about this could guide me, i really want to use the complete arcgis js api in my app without changing the way im working too much.

Thanks in advice! 😞

0 Kudos
TomWayson
Esri Contributor

I haven't looked in detail at your above code, but have you looked into the way these repos use the ArcGIS API for JavaScript with webpack?

Essentially they:

  1. configure webpack to exclude the esri and dojo modules
  2. output the ES6 code as AMD modules that can be loaded by Dojo
  3. include the ArcGIS API on the page from the CDN as a script tag

There's some good discussion of (the apparent lack of) any limitations to this approach: Question: Any limitations? · Issue #2 · lobsteropteryx/esri-webpack · GitHub 

Generally speaking, when writing ArcGIS API for JavaScript apps in ES6, I'd say that you are not "loading AMD modules in an ES6 way." Instead you writing ES6 modules and transpilling them into AMD modules that can be loaded by Dojo. In my experience, I've had the most success w/ approaches that exclude the Esri / Dojo from your local build and just output code to AMD that can be loaded by the CDN hosted ArcGIS API for JavaScript. I have another example that uses Rollup instead of webpack, but it's exact the same idea:

GitHub - tomwayson/esri-rollup-example: Example application using Rollup to bundle local ES2015 modu... 

HTH

EvelynHernandez
Occasional Contributor III

I still doesnt have clarity ... But i know webpack can transpilling them into amd modules.

The thing is how to do it now...

I have this in my webpack.config.js file (i see this code in the sites u gave me before)

What else should i set up there? am i in the right way?

var path = require('path');
module.exports = {
 entry: {
 login: './static/js/bundles/login.js',
 dashboard: './static/js/bundles/dashboard.js',
..

},
 output: {
 path: path.join(path.join(__dirname, 'dist'), 'js'),
 filename: '[name].js'
 },
 devServer: {
 inline: true,
 port: 443,
 host: "127.0.0.1"
 },
 module: {
 loaders: [
 {
 test: /\.(js|jsx)$/,
 exclude: /node_modules/,
 loader: 'babel',
 query: {
 presets: ['react', 'es2015', 'stage-2']
 }
 }
 ]
 },
 externals: [
 function(context, request, callback) {
 if (/^dojo/.test(request) ||
 /^dojox/.test(request) ||
 /^dijit/.test(request) ||
 /^esri/.test(request)
 ) {
 return callback(null, "amd " + request);
 }
 callback();
 }
 ]
};

Cuz im getting the following error:

Uncaught ReferenceError: __WEBPACK_EXTERNAL_MODULE_501__ is not defined

Thanks for all ur help.

0 Kudos
TomWayson
Esri Contributor

I don't use webpack (I develop in Ember day to day), so I can't diagnose your problem just by looking at your config.

I can tell you what my approach would be if I were you.

  1. fork the repo that's closest to what you want to do (I'm guessing GitHub - dcworldwide/esri-webpack: Demo app to build typescript apps using ESRI's JSAPI with webpack)
  2. follow the build instructions to get it working before you make any changes
  3. start adding whatever you need that is missing from that repo

If you get stuck, you can reach out to the other authors of those repos. They are much more likely to be able to help out if you can point them to your fork so they can pull it themselves and it out.

At some point, you'll decide if you are going to keep using that repo as a foundation for your project, or you'll realize what changes are needed to make your current app work. 

It is much easier to build up from something that is already working and find out what changes cause it to break than it is to start w/ something broken and try to get it working.

I regret that I cannot be of more help than that.

0 Kudos
EvelynHernandez
Occasional Contributor III

I have tried to find any example with the setup that i have but i still dont know how to do it with webpack, react and the arcgis js api.

I have that repo as an example, i hope somebody can help me 😞 .

GitHub - darklilium/CHQAves: Proyecto de colisión de aves CHQ 

0 Kudos
TomWayson
Esri Contributor

If the discussion in this GitHub issue helped you resolve the problems you had getting esri modules to load from ES6 code, would you mind making this question as answered?

Thanks! 

0 Kudos