Wildcard selectors in css path for grunt-contrib-compass - javascript

I'm trying to use grunt-contrib-compass for an AngularJS project with multiple app folders. Here is my basic directory structure:
/root
/appA
/appB
...
/appX
/public
/modules
/moduleName
/css
/sass
gruntfile.js is stored in /root
My compass task is set up as follows:
compass: {
dev: {
options: {
cssDir: 'app*/public/modules/**/css',
sassDir: 'app*/public/modules/**/sass',
outputStyle: 'compressed'
}
}
}
Note the wildcard selectors (*) in "cssDir" and "sassDir".
When this task runs, it successfully finds the .scss files in the directory specified for "sass". However, upon creating the .css files, it creates a new folder structure in /root like so:
/root
/app*
/public
/modules
/**
/css
The "css" folder is left empty and the actual .css file is saved in the same directory as my .scss files.
As an example, this is the terminal output for one of the .scss files when the compass task is run:
>> File "appStudentHousing/public/modules/studentHousingHome/sass/styles.scss" changed.
Running "compass:dev" (compass) task
directory appStudentHousing/public/modules/studentHousingHome/sass
write appStudentHousing/public/modules/studentHousingHome/sass/styles.css (0.003s)
It appears that the task recognizes wildcard selectors in the "sassDir" option, but it does not recognize them in the "cssDir" option. It creates a blank folder structure with the asterisks in the actual folder name, and then for some reason it saves the output .css file in the same folder as the .scss file.
Thanks much for any insight you can provide.

My comments converted into an answer:
Currently, the compass grunt plugin can only process single directories per target, thus no globbing that would match with multiple directories.
To circumvent this limitation, you always have the ability to create mutiple targets inside your compass task (Grunt functionality). A target is a subdivision of a task and can be used to setup different execution scenarios.
Two different targets for the compass plugin could look something similar to this:
compass: {
dev: {
options: {
cssDir: 'app/dev/modules/css',
sassDir: 'app/dev/modules/sass',
outputStyle: 'compressed'
}
},
live: {
options: {
cssDir: 'app/live/modules/css',
sassDir: 'app/live/modules/sass',
outputStyle: 'compressed'
}
}
}
This would give you two targets, dev and live, which specify different options. To execute each target individually, you simply call them on your command-line as follows:
$ grunt compass:dev
$ grunt compass:live
The naming of a target is totally up to you, there are no strict conventions to follow. If you have a single target for your task, then running the task like so:
$ grunt compass
Executes the single target. You do not need to explicitly specify it. However, if you have multiple targets in your task, then Grunt shall execute all of them in order when running with the above command.
And, as you have seen yourself, the official Grunt documentation gives you more detailed info regarding tasks and targets.

Related

set directory for node_modules within gruntfile.js

I would like to set the path of the node_modules directory within the gruntfile.js. I would like to have one central node_module directory for all my grunt projects.
Is it possible to set the path for an external node_module directory?
Current setup (which works)
projekt1
--gruntfile.js
--package.json
--node_modules
projekt2
--gruntfile.js
--package.json
--node_modules
Set up which I would like to have
node_modules
project1
--gruntfile.js
--package.json
project2
--gruntfile.js
--package.json
You can.... I have been using this setup without any issues. In each of your project Gruntfile.js files, simply set the base to one directory up like so:
Given a folder structure like this:
node_modules
project1
app.js
Gruntfile.js
package.json
Your Gruntfile.js may look something like this
module.exports = function(grunt) {
// Tell grunt where to find node_modules
// This is the line you're looking for
grunt.file.setBase('../');
// Your normal grunt config
grunt.initConfig({
// Your package.json file is now relative to the parent folder
pkg: grunt.file.readJSON('project1/package.json'),
// I use webpack, your tasks will probably be different
webpack: {
options: {},
build: {
// Paths are now resolved from the upper folder
// since we set the base path to one level up
entry: './project1/app.js',
output: {
// Again, the path must be relative to the parent folder
path: 'project1',
filename: 'app.min.js'
}
}
}
// etc...
});
// Load tasks...
}
Once you setBase('../') you'll need to make sure that all your file paths are resolved correctly since your base path has been changed to 1 level up.
A warning... if you publish or distribute your package, Grunt tasks won't work for those who download it because they more than likely won't have the same setup with node_modules 1 level up. And even if they do, they may not name the project1 folder the same

Launch Gulp Watch for JS and detect current folder has changed

I need to minimize the number of gulp's command from my gulpfile.
This is my JS folders
js/
templates/
t-01/
t-02/
[...]
t-xxx/
My gulp task for JS (with livereload)
gulp.task('da-js', function() {
gulp.src([
'js/templates/**/*.js',
'!js/templates/**/*.min.js'
])
.pipe(concat('app.min.js'))
.pipe(gulp.dest('js/templates'))
.pipe(livereload());
});
This task is global the destination folder is templates but I want to detect the current folder of js files like is :
I'm changing js in /templates/t-01/
gulp.watch is launching
app.min.js is generating only in this folder t-01
I know the gulp.dest is not correct to target current folder but I don't know how to do this.
Thank you for your help :)
You can use gulp's watch method to monitor a folder with JS files for updates and run a series of tasks in response to some change.
gulp.task('watch-files', function() {
gulp.watch('js/templates/**/*.js', ['da-js']);
});
Here we're watching over all the JS files in templates and all it's sub-folders and running your file concatenation task (da-js) for every update. Now that we're executing the same task, your app.min.js folder will be generated in your templates folder even when you change templates/t-01/some.js.
With the watch-files task defined in your gulpfile.js, you can simply run gulp watch-files command which will start monitoring your files.

Why does r.js combine and minify JS, then copy all the files to output dir?

I've been working with the RequireJS optimizer to create multiple optimized JS files for my project and have come across a problem that I’ve found mentioned in other posts but have not found a solution for.
When using r.js to optimized a single file, it pulls all the JS dependency into single file and drops it into the file specified by the “out” property in the build file. However, when trying to create two optimized files (i.e. multipage project using the ‘modules’ property), r.js creates two nicely optimized files but then drops ALL folders and files from the appDir into the output directory. That is, it pulls together and minifies all JS dependencies but then copies the individual files into the output directory.
I realize that r.js is not intended to be a deployment tool so is this by design or is there a way to tell r.js to not copy dependent files and directories into the output directory.
Yes, in your r.js build file, set the removeCombined option to true in order to preserve only the modules you specified to the output location.
{
...
//If set to true, any files that were combined into a build bundle will be
//removed from the output folder.
removeCombined: true,
...
}
See the r.js documentation's example build file.

What does "publicPath" in Webpack do?

Webpack docs state that output.publicPath is:
The output.path from the view of the JavaScript.
Could you please elaborate on what this actually means?
I use output.path and output.filename to specify where Webpack should output the result, but I’m not sure what to put in output.publicPath and whether it is required.
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js",
publicPath: "What should I put here?"
}
}
output.path
Local disk directory to store all your output files (Absolute path).
Example: path.join(__dirname, "build/")
Webpack will output everything into localdisk/path-to-your-project/build/
output.publicPath
Where you uploaded your bundled files. (absolute path, or relative to main HTML file)
Example: /assets/
Assumed you deployed the app at server root http://server/.
By using /assets/, the app will find webpack assets at: http://server/assets/. Under the hood, every urls that webpack encounters will be re-written to begin with "/assets/".
src="picture.jpg" Re-writes ➡ src="/assets/picture.jpg"
Accessed by: (http://server/assets/picture.jpg)
src="/img/picture.jpg" Re-writes ➡ src="/assets/img/picture.jpg"
Accessed by: (http://server/assets/img/picture.jpg)
When executed in the browser, webpack needs to know where you'll host the generated bundle. Thus it is able to request additional chunks (when using code splitting) or referenced files loaded via the file-loader or url-loader respectively.
For example: If you configure your http server to host the generated bundle under /assets/ you should write: publicPath: "/assets/"
the publicPath is just used for dev purpose, I was confused at first time I saw this config property, but it makes sense now that I've used webpack for a while
suppose you put all your js source file under src folder, and you config your webpack to build the source file to dist folder with output.path.
But you want to serve your static assets under a more meaningful location like webroot/public/assets, this time you can use out.publicPath='/webroot/public/assets', so that in your html, you can reference your js with <script src="/webroot/public/assets/bundle.js"></script>.
when you request webroot/public/assets/bundle.js the webpack-dev-server will find the js under the dist folder
Update:
thanks for Charlie Martin to correct my answer
original: the publicPath is just used for dev purpose, this is not just for dev purpose
No, this option is useful in the dev server, but its intention is for asynchronously loading script bundles in production. Say you have a very large single page application (for example Facebook). Facebook wouldn't want to serve all of its javascript every time you load the homepage, so it serves only whats needed on the homepage. Then, when you go to your profile, it loads some more javascript for that page with ajax. This option tells it where on your server to load that bundle from
filename specifies the name of file into which all your bundled code is going to get accumulated after going through build step.
path specifies the output directory where the app.js(filename) is going to get saved in the disk. If there is no output directory, webpack is going to create that directory for you.
for example:
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js"
}
}
This will create a directory myproject/examples/dist and under that directory it creates app.js, /myproject/examples/dist/app.js. After building, you can browse to myproject/examples/dist/app.js to see the bundled code
publicPath: "What should I put here?"
publicPath specifies the virtual directory in web server from where bundled file, app.js is going to get served up from. Keep in mind, the word server when using publicPath can be either webpack-dev-server or express server or other server that you can use with webpack.
for example
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js",
publicPath: path.resolve("/public/assets/js")
}
}
this configuration tells webpack to bundle all your js files into examples/dist/app.js and write into that file.
publicPath tells webpack-dev-server or express server to serve this bundled file ie examples/dist/app.js from specified virtual location in server ie /public/assets/js. So in your html file, you have to reference this file as
<script src="public/assets/js/app.js"></script>
So in summary, publicPath is like mapping between virtual directory in your server and output directory specified by output.path configuration, Whenever request for file public/assets/js/app.js comes, /examples/dist/app.js file will be served
You can use publicPath to point to the location where you want webpack-dev-server to serve its "virtual" files. The publicPath option will be the same location of the content-build option for webpack-dev-server. webpack-dev-server creates virtual files that it will use when you start it. These virtual files resemble the actual bundled files webpack creates. Basically you will want the --content-base option to point to the directory your index.html is in. Here is an example setup:
//application directory structure
/app/
/build/
/build/index.html
/webpack.config.js
//webpack.config.js
var path = require("path");
module.exports = {
...
output: {
path: path.resolve(__dirname, "build"),
publicPath: "/assets/",
filename: "bundle.js"
}
};
//index.html
<!DOCTYPE>
<html>
...
<script src="assets/bundle.js"></script>
</html>
//starting a webpack-dev-server from the command line
$ webpack-dev-server --content-base build
webpack-dev-server has created a virtual assets folder along with a virtual bundle.js file that it refers to. You can test this by going to localhost:8080/assets/bundle.js then check in your application for these files. They are only generated when you run the webpack-dev-server.
in my case,
i have a cdn,and i am going to place all my processed static files (js,imgs,fonts...) into my cdn,suppose the url is http://my.cdn.com/
so if there is a js file which is the orginal refer url in html is './js/my.js'
it should became http://my.cdn.com/js/my.js in production environment
in that case,what i need to do is just set publicpath equals http://my.cdn.com/
and webpack will automatic add that prefix
There are lots of good answers here, so I'll focus on output.publicPath: 'auto'.
Say when you build your project you get the next folder structure:
dist/blog/index.html
dist/app.js
dist/app.css
dist/index.html
In this case, both our index.html files have to have a correct path to our app.js and app.css (next - assets). Let's consider the next scenarios:
publicPath: '' or publicPath: '/':
When hosted on a server both point to the root of the website (ex. https://localhost:8080/), so everything works fine.
But should you try to open them locally, blog/index.html won't have a correct path to the assets. In case of publicPath: '' assets will be searched in the blog/ folder since that's where the relative path is pointing to. index.html still has the correct path to assets.
And in case of publicPath: '/', / points to the root of the filesystem, so neither of our index.html files will have a correct path to assets.
publicPath: 'auto':
In this case, both our index.html files will have relative paths to the assets. So, blog/index.html will be pointing to ../app.css, and index.html will be pointing to app.css.
The webpack2 documentation explains this in a much cleaner way:
https://webpack.js.org/guides/public-path/#use-cases
webpack has a highly useful configuration that let you specify the base path for all the assets on your application. It's called publicPath.
publicPath is used by webpack for the replacing relative path defined in your css for refering image and font file.

How can I configure my Grunt.js file to copy a directory without a particular subdirectory during the build?

Given that the Gruntfile is located in parent/aurora/Gruntfile.js,
I'd like to configure Grunt to do the following when the build command is executed:
copy the entire project directory into parent/build/aurora EXCEPT /parent/aurora/node_modules
once the directory haas been copied, create a zip file and delete the directory
https://github.com/antonpug/aurora/blob/master/Gruntfile.js
If you don't want to copy files or a directory you can just preface the files you don't want to include with !. For example, if you don't want to copy a directory just use: !/parent/aurora/node_modules/**.
In your grunt task:
files: [
{
src: ['your_files', '!/parent/aurora/node_modules/**'],
dest: 'output/folder'
}
]
Hope this helps!

Categories

Resources