I am having trouble building a layer for my web app. I have Node installed and I can use the packages directive to compress all my files but I cannot get a layer to build despite several days of trying every possible path and directive combination I can think of.
Here is a profile I thought should work:
var profile = {
// point basePath to ~/dev
basePath: "/Users/ferg/Dropbox/webdev/x-wing_squadron_builder/www/js/",
// point releaseDir to ~/dev/myapp-deploy
releaseDir: "./",
action:"release",
optimize:"shrinksafe",
stripConsole: "normal",
async: 1,
layers: {
"squad_builder_deploy/squad_builder_all": {
include: [
"squad_builder/SquadList.js",
"squad_builder/SquadPane.js" // there are actually many more files, this is just for testing...
]
}
},
resourceTags: {
amd: function(filename, mid) {
return /\.js$/.test(filename);
}
}
}
My directory structure is:
www
- js
- dojo_toolkit
- dojo
- dijit
- dojox
- squad_builder (my app)
- squad_builder_deploy (where I want to generate my layer)
Running this in the terminal:
buildscripts ferg$ ./build.sh load=build profile=../../../squad_builder/squad_builder -r
Gives me:
processing profile resource /Users/ferg/Dropbox/webdev/x-wing_squadron_builder/www/js/squad_builder/squad_builder.profile.js
discovering resources...
starting reading resources...
starting processing raw resource content...
starting tokenizing resource...
starting processing resource tokens...
starting parsing resource...
starting processing resource AST...
starting executing global optimizations...
starting writing resources...
error(303) Missing include module for layer. missing: squad_builder/SquadList.js; layer: squad_builder_deploy/squad_builder_all
error(303) Missing include module for layer. missing: squad_builder/SquadPane.js; layer: squad_builder_deploy/squad_builder_all
starting cleaning up...
waiting for the optimizer runner to finish...
starting reporting...
Report written to /Users/ferg/Dropbox/webdev/x-wing_squadron_builder/www/js/build-report.txt
Process finished normally.
errors: 2
warnings: 0
build time: 1.734 seconds
What am I doing wrong?
Module IDs are not file names. You should not have extensions on SquadList or SquadPane. You also should not be generating layers that aren’t files that already exist within your application. A layer is just an existing module file that contains many additional modules for efficiency.
Related
Good time of the day,
Recently I've been trying to implement dynamic module loading functionality for my project. However, I'm failing for past few hours. To give you an idea of what I'm trying to achieve, here is the structure of the project
plugins
developer
assets
scss
developer.scss
js
developer.js
themes
theme_name
webpack.mix.js
node_modules/
source
js
application.js
bootstrap.js
scss
application.scss
_variables.scss
So, in order to get the available plugins, I've made the following function
/**
* Get all plugins for specified developer
* which have 'assets' folder
* #param developerPath
* #param plugins
*/
function getDeveloperPlugins(developerPath, plugins) {
if (fs.existsSync(developerPath)) {
fs.readdirSync(developerPath).forEach(entry => {
let pluginPath = path.resolve(developerPath, entry),
assetsPath = path.resolve(pluginPath, 'assets');
if (fs.existsSync(assetsPath))
plugins[entry] = assetsPath;
});
}
}
This function loads all the available plugins for the specified developer, then goes inside and looks for the assets folder, if it exists, then it returns it and we can work with the provided directory later.
The next step is to generate the reference for every plugin (direct path to the developer_name.js file) which later should be 'mixed' into one plugins.bundle.js file.
In order to achieve this, the following piece of code 'emerged'
_.forEach(plugins, (directory, plugin) => {
let jsFolder = path.resolve(directory, 'js'),
scssFolder = path.resolve(directory, 'scss');
if (fs.existsSync(jsFolder)) {
webpackModules.push(jsFolder);
let possibleFile = path.resolve(jsFolder, plugin + '.js');
if (fs.existsSync(possibleFile))
pluginsBundle.js[plugin] = possibleFile;
}
if (fs.existsSync(scssFolder)) {
webpackModules.push(scssFolder);
let possibleFile = path.resolve(scssFolder, plugin + '.scss');
if (fs.existsSync(possibleFile))
pluginsBundle.scss[plugin] = possibleFile;
}
});
And the last step before I'm starting to edit the configuration of the Webpack is to get the folders for both scss and js files for all plugins and all developers:
let jsPluginsBundle = _.values(pluginsBundle.js),
scssPluginsBundle = _.values(pluginsBundle.scss);
And here is where the problems start to appear. I've tried many solutions offered either here on GitHub (in respective repositories), but I've failed so many times.
The only error I'm having now is this one:
ERROR in F:/Web/Projects/TestProject/plugins/developer/testplugin/assets/js/testplugin.js
Module build failed: ReferenceError: Unknown plugin "transform-object-rest-spread" specified in "base" at 0, attempted to resolve relative to "F:\\Web\\Projects\\TestProject\\plugins\\developer\\testplugin\\assets\\js"
Yes, i know that webpack.mix.js file should be in the root folder of the project, however, i'm just developing theme, which uses modules developed by other members of the team.
So, idea was to:
Start build process: npm run dev|prod
Load plugins for all needed developers automatically
Use methods and html tags provided by the plugin (it is a mix of PHP for API routing and Vue.js for Components, etc) as follows: <test-component></test-component>
Any help is really appreciated, i just cant get my head around that error. If you need extra information, i'm ready to help since i myself need help to solve this issue =)
Update: The latest Webpack config used by mix.webpackConfig() (still failing though)
let webpackConfiguration = {
module: {
rules: [{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: require.resolve('babel-loader'),
options: {
presets: [
'babel-preset-env'
].map(require.resolve),
plugins: [
'babel-plugin-transform-object-rest-spread'
].map(require.resolve)
}
}
}]
},
resolve: {
modules: webpackModules
}
};
mix.webpackConfig(webpackConfiguration);
And this is the content of the webpackModules variable:
[
'F:\\Web\\Projects\\TestProject\\themes\\testtheme\\node_modules',
'F:\\Web\\Projects\\TestProject\\themes\\testtheme',
'F:\\Web\\Projects\\TestProject\\plugins\\developer\\testplugin\\assets\\js',
'F:\\Web\\Projects\\TestProject\\plugins\\developer\\testplugin\\assets\\scss'
]
Okay, after 7 hours I've decided to try the most obvious method to solve the problem, to create node_modules folder in the root of the project and install laravel-mix there, and it worked like a charm.
Looks like, if it cant find the module in the directory outside the root scope of the Webpack, it will go up the tree to find the node_modules folder.
Developers should allow us to set the root folder for Webpack to fetch all the modules i guess, but well, problem is solved anyways.
I have a problem with my build in Dojo. It does build, and most of all widgets seems to be included in dojo.js after the build.
But when I test the built project it still loads about 100 files on demand.
I think the common denominator for the files that doesn't get build, is that they don't use return declare(
But instead returns functions or objects.
I attach a print-screen of some of the modules that doesn't get bundled in the build.
Dump from Firebug NET-console
The question is, is there some way of bundling these files into dojo.js, and avoid the 100+ extra requests?
Dojo builds are a pain in my neck. There are several different ways to configure them.
Generally, if you're trying to build everything (including Dojo) into one Javascript source file make sure your layer has "customBase" and "boot" set to "true".
build.profile.js
var profile = (function() {
return {
layers: {
"my/layer": {
customBase: true,
boot: true
}
}
}
}();
That should catch all of the Dojo source files. Otherwise, if something somehow slips that's what the "include" option is for. It's an explicit list of modules that get built into the layer.
build.profile.js
var profile = (function() {
return {
layers: {
"my/layer": {
include: [ "dojo/dojo", "dojo/date", ... ]
}
}
}
}();
I'm trying to combine both JS and JSX files (to use with React.js) in a single, versioned all.js file.
My current Gulpfile:
var elixir = require('laravel-elixir');
elixir.config.sourcemaps = false;
elixir(function(mix) {
mix
.less([
'app.less'
], null, 'resources/assets/less')
.babel([
'libs/**', //contains react.js among other libs (jquery, bootstrap)
'app.js', //contains normal jquery
'quiz/quiz.jsx'
], null, 'resources/assets/js')
//.babel([
//'quiz/quiz.jsx'
//])
.version(["css/app.css", "js/all.js"]);
});
Output:
[18:38:28] Starting 'default'...
[18:38:28] Starting 'less'...
Fetching Less Source Files...
- resources/assets/less/app.less
Saving To...
- public/css/app.css
[18:38:30] Finished 'default' after 1.91 s
[18:38:34] gulp-notify: [Laravel Elixir] Less Compiled!
[18:38:34] Finished 'less' after 6 s
[18:38:34] Starting 'babel'...
Fetching Babel Source Files...
- resources/assets/js/libs/**/**/*
- resources/assets/js/app.js
- resources/assets/js/quiz/quiz.jsx
Saving To...
- public/js/all.js <---- STUCK HERE
It's been stuck there for a while and I'm not sure how to debug this.
Changing the first babel() with scripts() works, but of course won't compile the JSX file (and won't complain about it).
Calling babel after scripts (the 3 commented out lines) will correctly compile the JSX file, but without everything else (it will simply compile the JSX and save it to all.js).
How can I fix this?
I'm using the following architecture for my multipage requirejs based application.:
https://github.com/requirejs/example-multipage-shim
The repository explains how to optimize the application by running r.js, the command line tool used for this kind of task.
Everything should work fine but my project as some modules that have dependencies that perform HTTP GET request to fetch data from server (wich can be text or json)
This is because some of my jsons and templates used by some pages need to be server-side processed for localization.
Here is a basic example to show what i'm talking about:
define( function( require ){
var appLang = require('json!/pagelang/login'), //(a)
loginTemplate = require('text!/template/login'), //(b)
module = require('app/model/user'), //(c)
....
An HTTP get request is made to my server localhost/pagelang/login
which returns a json
{
"hash": "translated_value",
...
}
The same applied for template/template_namewhere an html with it's UI translated into the user language is returned from the server.
By running r.js it attempts to load those locations for an existant directory directory on the server, which obviously, don't exist.
Tracing dependencies for: app/main/login
Error: Error: Loader plugin did not call the load callback in the build:
json:
json!/pagelang/login: Error: ENOENT, no such file or directory '/pagelang/login'
Module loading did not complete for: app/main/login
So, i would like to prevent the command line tool from optimizing text! and json! modules. Is it possible?
I checked requirejs build settings but i didn't find the solution for my problem. Any help?
https://github.com/jrburke/r.js/blob/master/build/example.build.js
The json plugin uses if (( config.isBuild && (config.inlineJSON === false || name.indexOf(CACHE_BUST_QUERY_PARAM +'=') !== -1)) || (url.indexOf('empty:') === 0)) { when the optimiser runs so you have a couple of options.
Add the build config option inlineJSON: false,
Add !bust to the end of the json require. require('json!/pagelang/login!bust'), or
Add the path to the build config option paths: { "/pagelang/login": "empty:" }
The text plugin uses if (config.isBuild && !config.inlineText) { and if (url.indexOf('empty:') === 0) {
Set the build config option inlineText: false, or
Add the path to the build config option paths: { "/template/login": "empty:" }
=================================================================
Update: if you can't get the option inlineJSON to work, try using inlineText, which seems to cover JSON as well.
Reference: https://github.com/requirejs/r.js/blob/master/build/example.build.js
I just installed grunt spritesheet onto my Windows system, and when I try to run the package, I get an error for this task: "grunt.spritesheet requires a sprites and sheet property".
The package looks loaded correctly, and runs with all of the other tasks with grunt. I have the Python2.7 and Cairo dependencies loaded as well.
In my main gruntfile (which already has require, jshint, and compass running fine), I added:
spritesheet: {
// An array of filename / source images array pairs. The basename of the sprite file
// is also prefixed to the CSS classes.
sprites: {
"images/icons/sprite.png": ['images/icons/*.png']
},
// The destination for the build stylesheet
sheet: "scss/homepsprite.css"
}
So, the properties "sprites" and "sheet" are clearly there. Is there something else that I'm missing? The package is loading fine with the rest of the grunt modules... I have
grunt.loadNpmTasks('grunt-spritesheet');
in my gruntfile as well as
grunt.registerTask("default", ["jshint", "requirejs:dev", "compass:dev", "spritesheet"]);
Thanks for any feedback.
grunt-spritesheet is a multitask which #implicitly iterates over all of its named sub-properties#.
you could see that grunt is probably trying to run "sprites" and "sheet" as a task:
Running "spritesheet:sprites" (spritesheet) task
that means that the documentation is somewhat not so clear, and you need a "name" for your task which could basically be anything (i use generate here):
spritesheet: {
generate: {
// An array of filename / source images array pairs. The basename of the sprite file
// is also prefixed to the CSS classes.
sprites: {
"images/icons/sprite.png": ['images/icons/*.png']
},
// The destination for the build stylesheet
sheet: "scss/homepsprite.css"
}
}
the output should now be:
Running "spritesheet:generate" (spritesheet) task