Is the word base a "magic" word in RequireJS?
What does it refer to by default?
As you confirmed, Karma is likely your culprit, which puts all resources on /base before running.
First, confirm you have the npm package "karma-requirejs" installed.
Check your Karma config file and ensure you have the "frameworks" array include "requirejs". Here's what mine looks like:
frameworks: ['jasmine', 'requirejs'],
Also, in your files array, have the last file be your require config and all other files above specifying not to be included on page load (included: false). Again, here's a sample from one of my projects Karma config files:
files: [
//other files here, such as:
{ pattern: 'app.js', included: false },
// require config needs to be last; see http://karma-runner.github.io/0.12/plus/requirejs.html
'config/require.config.js'
],
Please note that my require config bootstraps the application as well by calling require(["app"]), which starts the require/fetch process.
Assuming:
"baseUrl" is pointing to your webroot (it can be relative),
"frameworks" includes "requirejs",
"files" array includes all your dependencies but doesn't included them up front (that's require's job) and the config is last to follow,
...you should have good karma. :)
Good luck!
Related
Architecture
I would like to share code between client and server side. I have defined aliases in the webpack config:
resolve: {
// Absolute paths: https://github.com/webpack/webpack/issues/109
alias: {
server : absPath('/src/server/'),
app : absPath('/src/app/'),
client : absPath('/src/client/'),
}
},
Problem
Now on the server side I need to include webpack in order to recognize the correct paths when I require a file. For example
require('app/somefile.js')
will fail in pure node.js because can't find the app folder.
What I need (read the What I need updated section)
I need to be able to use the webpack aliases. I was thinking about making a bundle of all the server part without any file from node_modules. In this way when the server starts it will use node_modules from the node_modules folder instead of a minified js file (Why? 1st: it doesn't work. 2nd: is bad, because node_modules are compiled based on platform. So I don't want my win files to go on a unix server).
Output:
Compiled server.js file without any node_modules included.
Let the server.js to use node_modules;
What I need updated
As I've noticed in https://github.com/webpack/webpack/issues/135 making a bundled server.js will mess up with all the io operation file paths.
A better idea would be to leave node.js server files as they are, but replace the require method provided with a custom webpack require which takes in account configurations such as aliases (others?)... Can be done how require.js has done to run on node.js server.
What I've tried
By adding this plugin in webpack
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"ignore", /* filename= */"server.bundle.js")
Entries:
entry: {
client: "./src/client/index.js",
server: "./src/server/index.js",
ignore: ['the_only_node_module'] // But I need to do that for every node_module
},
It will create a file server.js which only contains my server code. Then creates a server.bundle.js which is not used. But the problem is that webpack includes the webpackJsonp function in the server.bundle.js file. Therefore both the client and server will not work.
It should be a way to just disable node_modules on one entry.
What I've tried # 2
I've managed to exclude the path, but requires doesn't work because are already minified. So the source looks like require(3) instead of require('my-module'). Each require string has been converted to an integer so it doesn't work.
In order to work I also need to patch the require function that webpack exports to add the node.js native require function (this is easy manually, but should be done automatically).
What I've tried # 3
In the webpack configuration:
{target: "node"}
This only adds an exports variable (not sure about what else it does because I've diffed the output).
What I've tried # 4 (almost there)
Using
require.ensure('my_module')
and then replacing all occurrences of r(2).ensure with require. I don't know if the r(2) part is always the same and because of this might not be automated.
Solved
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
Related
https://www.bountysource.com/issues/1660629-what-s-the-right-way-to-use-webpack-specific-functionality-in-node-js
https://github.com/webpack/webpack/issues/135
http://webpack.github.io/docs/configuration.html#target
https://github.com/webpack/webpack/issues/458
How to simultaneously create both 'web' and 'node' versions of a bundle with Webpack?
http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/
Thanks
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
My solution was:
{
// make sure that webpack will externalize
// modules using Node's module API (CommonJS 2)
output: { ...output, libraryTarget: 'commonjs2' },
// externalize all require() calls to non-relative modules.
// Unless you do something funky, every time you import a module
// from node_modules, it should match the regex below
externals: /^[a-z0-9-]/,
// Optional: use this if you want to be able to require() the
// server bundles from Node.js later
target: 'node'
}
Trying to get karma working with requirejs. I don't understand why I am getting all of these errors when running Karma:
ERROR: 'There is no timestamp for /base/test/mainSpec.js?bust=1387739317116!'
ERROR: 'There is no timestamp for /base/app/main.js?bust=1387739317116!'
ERROR: 'There is no timestamp for /base/bower_components/jquery/jquery.js?bust=1387739317116!'
When I go to the network tab in inspector, all of the files are there with no 404s.
I'm a little confused because karma seems to be looking for a 'base' directory but there is no 'base' directory in my project. According to the karma docs:
Karma serves files under the /base directory. So, on the server
requests to files will be served up under
http://localhost:9876/base/*. The Require.js config for baseUrl gives
a starting context for modules that load with relative paths. When
setting this value for the Karma server it will need to start with
/base. We want the baseUrl for our tests to be the same folder as the
base url we have in src/main.js, so that relative requires in the
source won’t need to change. So, as we want our base url to be at
src/, we need to write /base/src.
This confusing to say the least. Am I supposed to have a baseUrl configuration in my main.js file that points to '/base'?
note: This post was valid by Karma in 2014 Jan 16. I am not certain of the current state of that lib, maybe they fixed their weird configuration logic and added meaningful error messages. If not, then this post can be probably very helpful by fixing configuration issues related to Karma.
These kind of errors occur by misconfiguration. You should add everything your test uses to the file patterns in your config file.
For example:
module.exports = function (config) {
config.set({
basePath: './',
frameworks: ['jasmine', 'requirejs'],
files: [
{pattern: 'test/bootstrap.js', included: true},
{pattern: 'test/**/*.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'vendor/**/*.js', included: false}
],
exclude: [
],
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Firefox'],
captureTimeout: 6000,
singleRun: false
});
};
In this example the bootstrap.js is the only file included by Karma in the HTML, the other files are dependencies which are loaded by the code in the bootstrap.js. The pattern order is very important and sadly it is far from logical: the next pattern does not override the previous one. So if I'd give the test/**/*.js pattern as first and test/bootstrap.js as second, it would not work because the bootstrap would not be included. In these cases Karma sends you an "empty testsuite" message, which is useless if you don't know how to configure it...
If your tests try to use a file which is not covered by the patterns you gave in your Karma configuration file, then you will get the "There is no timestamp for xy" error message, which is very similar to the previously mentioned "empty testsuite". If you don't know the system you won't have a clue, what it means, or what you have to do in order to fix it ...
The exclude part of the configuration object is for files, which have been added to the file patterns for inclusion, but you don't want to include or use them in your tests. These can be for example requirejs configuration files for development and production environments, etc...
For me it was simply making the mistake of setting basePath: 'base' instead of baseUrl: '/base'.
baseUrl: '/base' ftw!
The basePath is to identify the root of your project relative to the configuration file (karma.conf.js). Take a look at this example: https://github.com/karma-runner/karma/blob/v0.8.5/test/client/karma.conf.js
In the browser, I also got this error about the timestamp but it doesn't affect anything. The tests are working properly. I guess it should be a warning more than an error :-)
Jeff's right, you should exclude the requirejs config file of your app, because "we don't want to actually start the application in our tests. [LINK]".
The test-main.js config file is a separate file from the requirejs config file your app uses, which in your case might be config.js or main.js, depending on where you config your requirejs.
They both configures path and dependencies (could be specifying about the same ones), but the former is to provide requirejs support for the tests you write. This whole requirejs setup is a separate one from the requirejs you use in your app. So don't include the latter, it confuses Karma.
And the link above is a working Karma with its requirejs demo, check it out.
After trying all the solutions posted on different sources, Finally I got it Fixed. Check it here: Make "no timestamp" error configurable #6 .
Example from the issue for the karma.conf.js file:
client: {
requireJsShowNoTimestampsError: '^(?!.*(^/base/app/node_modules/))'
}
in my karma.conf.js file, I simply excluded my file that contained my require.config function (in my case happened to be config.js) and the errors went away.
exclude: [
'app/config.js',
'bower_components/jasmine/**/*.js'
],
This error can also happen when the files in question don't actually exist!
So check to make sure that the file you're getting this error for actually exists in your project!
Once you find out what the files are, you can ignore them using a pattern like so in your karma.conf.js, if it turns out their existence should be ignored in some cases:
exclude: [
'path/to/files/to/ignore/**/*.js'
]
I had an exact same error in my project and I found that the best and fastest way to debug where is the problem is to list the files that our karma have loaded.
If you used karma init (if not, just do it) and respond YES to the question about the usage of RequireJS you probably have a file like this:
var tests = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
var BASE_URL = '/base/build/js';
var BASE_URL_REGEXP = /^\/base\/build\/js\/|\.js$/g;
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function (file) {
console.log(file;) // ADD THIS CONSOLE LOG TO LIST LOADED FILES
if (TEST_REGEXP.test(file)) {
var normalizedTestModule = file.replace(BASE_URL_REGEXP, '')
tests.push(normalizedTestModule)
}
})
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: BASE_URL,
paths: {
},
shim: {
},
deps: tests,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
})
Then you can play with your karam.conf.js file and load new files to check whats going on in karma local path.
Expanding from #Naruto Sempai's answer:
I resolved this issue by first setting the basePath attribute in my karma.conf.js file. This path contains the needed ../ (previous directory) strings until my path was at the root of my source/test files.
Then I modified my test-main.js file (containing my RequireJS configuration) and set the baseUrl to /base.
Now, no timestamp errors.
--
To illustrate my environment and paths I configured, heres a basic setup example:
Source file location:
/Users/ben/some-project/src/main/resources/var/www/project/js/app
Test file location:
/Users/ben/some-project/src/test/var/www/project/
Karma Config location:
/Users/ben/some-project/src/test/var/www/project/karma.conf.js
Test RequireJS Config location:
/Users/ben/some-project/src/test/var/www/project/test-main.js
My karma.conf.js:
module.exports = function (config) {
config.set({
basePath: '../../../../'
});
}
to make my "root" at /Users/ben/some-project/src/.
My test-main.js:
requirejs.config({
baseUrl: '/base'
});
I'm working on an application built with Brunch. I would like to load some* of the vendor-supplied javascript as modules, so that I can require them in my code, rather than relying on global variables. Is there some way to do this, without copying all the vendor code into my app directory?
I tried creating a vendorlib directory, but brunch doesn't seem to look anywhere bu app and vendor. I also tried making a vendor/modules directory, but brunch seems to not wrap anything found under vendor (even when I convinced it to combine those files with the files other modules found under app.)
*The "some" that I'm working on right now are Chaplin, Backbone and Underscore. If I get those to work, I'll move more over later.
You can override config.modules.wrapper and make it wrap, for example, all files in vendor/modules directory. Or you can make add more directories that are handled by brunch to config.paths.watched.
For those following along at home, this is what my config.coffee eventually looked like:
paths:
watched: ['app','vendor','test','vendorlib']
files:
javascripts:
joinTo:
'javascripts/app.js': /^app/
'javascripts/vendor.js': /^vendor/
'test/javascripts/test.js': /^test[\\/](?!vendor)/
'test/javascripts/test-vendor.js': /^test[\\/](?=vendor)/
order:
# Files in `vendor` directories are compiled before other files
# even if they aren't specified in order.before.
before: [
'vendor/scripts/console-polyfill.js',
]
after: [
'test/vendor/scripts/test-helper.js'
]
stylesheets:
joinTo:
'stylesheets/app.css': /^(app|vendor)/
'test/stylesheets/test.css': /^test/
order:
after: ['vendor/styles/helpers.css']
templates:
joinTo: 'javascripts/app.js'
modules:
nameCleaner: (path) ->
path.replace(/^(app|vendorlib)\//, '')
This lets me populate a vendorlib directory with modules from vendors that support loading as modules. I currently have Chaplin, jQuery, and Backbone in there. I had to rename them not to include the version numbers.
I am trying to integrate the r.js optimizer on the server side (Apache Sling) and face one problem: when resolving modules it always looks them up under the output directory (dir), not from within the source directory (baseUrl or appDir), doesn't find them and thus fails.
/project/build.js
({
name: "modules/main",
dir: "/target",
baseUrl: "/sources"
})
If you wonder, the root path / is inside the server's JCR repository, not a file system. Also I simplified the example a bit (hopefully without concealing the issue).
It will resolve and read the main file properly:
/sources/modules/main.js
require(["modules/foo"]);
However, when it now tries to resolve modules/foo, it tries to read it from /target/modules/foo.js instead of /sources/modules/foo.js as I would expect, which does not exist and the whole r.js execution fails and stops.
I tried using appDir and all kinds of combinations, but the issue is always the same. I am fairly sure it is not related to my integration code... AFAIU from documentation and googling around, it should either copy them to the target before building the optimized file or simply pick them up from the source directory automatically.
Am I supposed to copy all the raw source files to /target myself before running r.js?
Maybe the problem is that baseUrl=/overlay is different from build.js residing inside /project?
Maybe r.js also looks at the current working directory of the r.js process (which is so far undefined in my case)?
Can the output directory (dir) live outside appDir or baseUrl?
My require.js configuration looks like so:
({
appDir: "../app",
baseUrl: "js/lib", // means the base URL is ../app/js/lib
dir: "../app-built", //target
// offtopic, but a very handy option
mainConfigFile: "../app/config.js",
// I'm not 100% sure if it's equivalent to your version
// where you're not using "modules" and just "name"
modules: [{
name: "../some/main" // this is ../app/js/some/main.js
}]
})
Reading through https://github.com/jrburke/r.js/blob/master/build/example.build.js#L15 - it seems you do want an appDir specified if you want the files to be copied to the target dir before optimization.
To answer your other questions
you don't need to manually copy files over
baseUrl should point to the same place as baseUrl used in your app's config - however you have to adjust it depending on what appDir you choose to use (e.g. appDir="../app" and baseUrl="js/lib", or appDir="../app/js" then baseUrl="lib", etc.)
appDir and dir should be relative to the build config file - I don't know what happens when you use absolute paths
yes - output dir does (has to?) live outside appDir. BaseURL is within the appDir/dir (all these names are really confusing..)
I would say
use the "appDir" setting
try using "modules" like I did instead of just "name"
make "appDir" and "dir" relative paths to the build file if you can - these absolute paths might be what's breaking? because other than that the config looks very similar to the one I use
I know there's a different way of configuring it where your output is 1 file, which case the files are read from the source dir - but I haven't used that much myself.
Hope this helps.
Answering myself: I got it to work with the single output file approach using out instead of appDir or dir:
({
name: "modules/main",
baseUrl: "/sources"
out: "/target/out.js",
})
In this case it reads all the modules from the sources and creates a /target/out-temp.js which it then moves to /target/out.js when done.
This seems to suit my needs so far.
I've got some paths configured in require-config.js as follows:
var require = {
baseUrl: '/javascript',
paths: {
'jquery': 'jquery/jquery-1.8.1.min'
// etc. -- several paths to vendor files here
},
}
I am trying to get the optimization working for deployment. The docs say I should have a build.js that looks something like this:
({
baseUrl: 'javascript',
paths: {
'jquery': 'jquery/jquery-1.8.1.min'
},
name: 'main',
out: 'main-build.js'
})
Is there a way to have the optimizer read my config file instead of (or in addition to) build.js? I don't want to have to manually keep the paths configured the same in both files if they change.
I tried to just run node r.js -o path/to/require-config.js, but it threw an error, "malformed: SyntaxError: Unexpected token var"
Edit: for clarification, my require-config.js file is the config only, not my main module. I did this so I could use the same configuration but load a different main module when unit testing.
You'll need to adjust the way your config options are defined. Taken from the RequireJS documentation:
In version 1.0.5+ of the optimizer, the mainConfigFile option can be used to specify the location of the runtime config. If specified with the path to your main JS file, the first requirejs({}), requirejs.config({}), require({}), or require.config({}) found in that file will be parsed out and used as part of the configuration options passed to the optimizer:
So basically you can point your r.js build file to your config options that will also be shared with the browser.
You will need to make use of the mainConfigFile option
For other's reference:
https://github.com/jrburke/r.js/blob/master/build/example.build.js
The build settings (no need to repeat your config.js lib inclusions here):
baseUrl: 'app',
name: 'assets/js/lib/almond', // or require
// Read config and then also build it into the app
mainConfigFile: 'app/config.js',
include: ['config'],
// Needed for almond (and does no harm for require)
wrap: true,