Larz
Larz

Reputation: 1186

RequireJS - what should I set for the BaseUrl?

I'm having trouble understanding how to set the base URL for requirejs given the structure of my project.

The issue: Not all html files will be on the same folder level. The script file paths keep changing depending on the location of the html page.

What I've tried: I've scoured the API, but I just don't understand what the BaseURL should be to get the correct path for all pages. I've tested variations (../js/lib, /js/lib/, I tried not including it all in the main.js file) but this one below is the only one that seems to produce the correct result on certain files.

Main.js

requirejs.config({
    baseUrl: '../js/lib',    
    paths: {
        'jquery' : (document.addEventListener) ? ['vendor/jquery'] : ['vendor/jquery-1.9.1']
    },
    shim: {
        'foundation/foundation': {
            deps: ['jquery']
        },
        'foundation/foundation.alert': {
            deps: ['jquery', 'foundation/foundation']
        },            
        'vendor/slick.min': {
            deps: [
                'jquery',
                'foundation',
                'foundation/foundation.interchange'
            ],
            exports: 'slick'
        }
    }
});
requirejs(['jquery'
    , 'foundation/foundation'   
]);

Folder Structure

Main Folder
│
│  Some Folder
│  ├── css
│  ├── js
│  │   ├── lib
│  │   │   ├── foundation
│  │   │   │   ├── foundation.alert.js
│  │   │   │   ├── ...(foundation component js files)
│  │   │   │   ├── foundation.js
│  │   │   ├── vendor
│  │   │   │   ├── jquery-1.9.1.js
│  │   │   │   ├── jquery.js
│  │   │   ├── foundation.min.js
│  │   │   ├── slick.min.js
│  │   │   └── slickModule.js
│  │   ├── main.js
│  │   └── require.js   
│  ├── html
│  │   ├── components
│  │   │   ├── slider.html    [All scripts throw 404: Main Folder/Some Folder/html/js/lib/vendor/file.js ]
│  │   ├── home.html           [loads files as expected]
│  │   ├── second.html         [loads files as expected]
│  │   ├── subfolder
│  │   │   └── random.html
│  ├── extra folder
│  │   └── index.html   [All scripts throw 404: Main Folder/Some Folder/extra folder/js/lib/vendor/file.js ]
│  │
│  Another Folder
│  ├── index.html [All scripts throw 404]

/html/components/slider.html

When I try to call require this way, the slickModule's url is "Main Folder/Some Folder/html/js/lib/slickModule.js" - note 'html' is added after the base url

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
    <script data-main="../../js/main" src="../../js/require.js"></script>
    <script>
        require(['../js/main'], function () {
            require(['slickModule']);
        });
    </script>
</head>
<body>
...
</body>
</html>

Could someone help me to see why this could be happening?

If it's even possible, what can I do to get the base URL to be consistent?

Upvotes: 3

Views: 11050

Answers (3)

rockerest
rockerest

Reputation: 10508

Summary

  1. Don't require the same file twice in a row, especially if it's the file that changes your configuration options, especially if it uses relative paths.
  2. Use a single application entry-point. If you can't start your application in a single place, it will be difficult (though not impossible) to use the data-main attribute.
  3. Use the paths configuration option to point to files, not relative paths when you're including the module or setting up the config.

Single Entry Point

First of all, you're likely running into some issues with your data-main attribute since its behavior when used for multiple entry points is undocumented. As it says:

If you want to to do require() calls in the HTML page, then it is best to not use data-main. data-main is only intended for use when the page just has one main entry point, the data-main script. For pages that want to do inline require() calls, it is best to nest those inside a require() call for the configuration

Multiple requires

Secondly, you're using the data-main attribute to load your config which defines the behavior of the library (in other words, the require/requirejs function is customized), but then you use that customized tool to load the configuration again:

<script data-main="../../js/main" src="../../js/require.js"></script>
<script>
    require(['../js/main'], function () {
        require(['slickModule']);
    });
</script>

I'm almost positive this introduces some strange behavior.

Use paths to avoid ../

Third, your baseUrl is automatically set to either the location of the HTML that loaded it, or the location of the data-main script. You can use this to your advantage by creating a single entry point (probably js/main), and then defining the paths configuration option to hide nested modules.

In other words, your application should never need to request ../ (or any variation thereof) because anything nested should be hidden by a paths entry like:

"paths": {
    "slickModule": "lib/slickModule"
}

I know this answer doesn't specifically solve your problem, but I'm positive that one of these issues - when corrected - will solve your 404 problem.

Upvotes: 5

mmgross
mmgross

Reputation: 3092

Since you have html-files in different folders at different levels, setting your baseUrl as a relative path (i.e. ../lib/js) will work for some files, but for all, that's to be expected. You need to set an absolute path, from your root directory to your lib folder, e.g. if 'Main Folder' is your root, your baseUrl should be /Some Folder/js/lib/ or /Some Folder/js/lib. I hope that helps.

Upvotes: 0

Cᴏʀʏ
Cᴏʀʏ

Reputation: 107536

I had this same issue in an ASP.NET MVC4 application, structured like so:

Main Folder
├── Scripts
│   ├── Libraries
│   │   ├── jquery
│   │   |   ├── jquery-1.10.2.min.js
...

What I did was use my server side technology's method to determine the app's "root location". In my case, this is HttpRequest.ApplicationPath, which "gets the ASP.NET application's virtual application root path on the server." (source).

My requirejs setup looks like:

<script type="text/javascript">
    var require = {
        baseUrl: '@(Request.ApplicationPath)/Scripts',
        paths: {
            jquery: 'Libraries/jquery/jquery-1.10.2.min',
            ...
        }
    }
</script>
<script type="text/javascript" src="@Url.Content("~/Scripts/Libraries/require/require.js")"></script>

To summarize:

  • My base URL is the root application path plus the Scripts folder
  • Each path starts with the folder that is a child of Scripts
  • This forces requirejs to use an absolute path to the libraries instead of trying to figure out the relative ones from various directories.
  • Any scripts not specified in the paths configuration should also start with the folder that is a child of Scripts
  • You shouldn't need to use ../ anywhere in your configuration

Hope that helps, obviously you'll need to adjust this for whatever technology you're using.

Upvotes: 4

Related Questions