I'm trying to figure out a workflow involving postcss. My need is to have css partials in one folder, watch them and output a bundle css file. The bundle css file must have include a base.css file at the top.
postcss has a --watch flag and can watch multiple files but can only output multiple files and not a bundle css file. I can use cat to combine all the files and use stdin to pipe them to postcss. But I can't trigger the cat command from postcss.
My files structure could look like this:
partials/
|_one.css
|_two.css
styles/
|_base.css
|_bundle.css
How would I, by using npm, arrange my script section to use CLI commands to achieve my goal?
My main issue is to figure out how to orchestra the build steps without one step blocking the next. A link to a working work-flow example would be great!
EDIT I got a solution working but it is very suboptimal as it can not be used with sourcemaps, can not have global variables and is a two step process. But I will outline it here in hope that someone can suggest a better approach.
Using the following structure:
build/
|_stylesheet/
|_default.css (final processed css)
partials/
|_one.css
|_one.htm (html snippet example)
|_two.css
|_two.htm (html snippet example)
styles/
|_base.css
|_bundle/ (css files from partial/ that is partly processed)
|_one.css
|_two.css
|_master.css (import rules)
I have a two step process in my package.json. First I make sure I have a styles/bundle folder (mkdir -p) and then I start nodemon to watch the css files in partials/. When a change occurs, nodemon runs npm run css:build.
css:build process the css files in partials/ and output them in styles/bundle/ (remember that I don't know how to watch multiple files and output one bundled file).
After running css:build, npm runs postcss:build which processes the master.css file that #import css files from styles/bundle/. I then output (>) the processed content from stdout to build/stylesheet/default.css.
{
"css": "mkdir -p styles/bundle && nodemon -I --ext css --watch partials/ --exec 'npm run css:build'",
"css:build": "postcss --use lost --use postcss-cssnext --dir styles/bundle/ partials/*.css",
"postcss:build": "postcss --use postcss-import --use postcss-cssnext --use cssnano styles/master.css > build/stylesheet/default.css",
}
You can check out watch and parallelshell packages from npm. I believe the combo of those two will do the trick. More on that here: http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/
Maybe you should consider using webpack instead to build a single css file and other resources which also has a watch flag. It is very efficient and you don't need to manually rebuild all the time after changes to resources/files.
Related
Within the root directory of my project, I run the following command using npm and html-minifier-terser:
npx html-minifier-terser --input-dir src/ --output-dir dist/ src/index.html -o index.min.html --file-ext html
The output file to dist/ is index.html and not index.min.html.
I tried to install html-minifier-terser globally, which does not help. I then tried to remove the specification of input and output directories within the command, which resulted in the expected behavior.
Any suggestions why I can't get dist/index.min.html to work?
Doing a little more research, I found a solution on this thread ng build production should minify index.html in dist.
The workaround is to omit using the input and output directory arguments and instead specify the output path as in --output dist/index.min.html.
i am new to node and react so please forgive me if this does not sound correct.
I will try to explain this as simple as possible, but would like to know if this process can be automated somehow during a script/build process.
I create a component called 'button.js' in lib folder.
i added a script in the package.json file. the script is "build": "babel lib -d build",
I run npm run build which creates a build folder with my 'button' component built.
i export the component in an index.js file like so:
export { default as Button } from './build/components/Button'
I am wondering if the final 2 steps can be combined into a single step i.e. build the component then export it into the index.js file? If so, could you please point me in the right direction of how this can be done?
It sounds like you're trying to manually manage a "monorepos", whereby you have lots of individual packages that are utilised as node modules within other packages in your solution.
I'd suggest checking out Lerna (https://github.com/lerna/lerna) which takes away some of this pain. It allows you to include internal modules into your packages as if they were normal, published npm modules.
I suggest you google on webpack. It's how most people turn a bunch of js files into a bundle.js file. This is making your website faster too, as clients only need to load 1 file.
Webpack is a big subject so look for a "webpack babel react" guide.
I'm using browserify with npm to create a bundle of js. The web app using react and a lot of other modules so the output file is about 3.4M, 2M uglyfied and 430K gzip.
The browserify process is executed via npm run browserify that is defined in package.json
"browserify": "browserify client/index.js -u server/**/**/**/* -i q -i express-validation | uglifyjs -o public/javascripts/generated/bundle.js"
I have a feeling that the bundle output is too large and there is a way to reduce it but I couldn't find a way to debug the process (tried -d --list, etc).
Any help will be appreciated.
This could represent a difficult and annoying refactoring step in your situation, but in accordance with the official browserify handbook, you could try the partition feature, this way, you can split the final bundle into multiples files, for an incremental injection of the project dependencies, in the hope to reduce the size of the initial file required by the entry point of your app.
To achieve this, you can use the factor-bundle or partition-bundle plugins, the main difference between them, is that the second plugin have a built-in ajax function (loadjs) to load the js files, IMHO the most flexible solution for large applications.
Follows the official partion-bundle description from the Browserify handbook:
partition-bundle
partition-bundle handles splitting output into multiple bundles like
factor-bundle, but includes a built-in loader using a special loadjs()
function.
partition-bundle takes a json file that maps source files to bundle
files:
{
"entry.js": ["./a"],
"common.js": ["./b"],
"common/extra.js": ["./e", "./d"]
}
Then partition-bundle is loaded as a plugin and the mapping file,
output directory, and destination url path (required for dynamic
loading) are passed in:
browserify -p [ partition-bundle --map mapping.json \
--output output/directory --url directory ]
Now you can add:
<script src="entry.js"></script>
to your page to load the entry file. From inside the entry file, you
can dynamically load other bundles with a loadjs() function:
a.addEventListener('click', function() {
loadjs(['./e', './d'], function(e, d) {
console.log(e, d);
});
});
Additionally you can use Disc, to visually analyze your dependencies tree, to avoid the redundancies/replicates inside it and/or identify dependencies not required during the application startup.
From the official Disc website:
Disc is a tool for analyzing the module tree of browserify project
bundles. It's especially handy for catching large and/or duplicate
modules which might be either bloating up your bundle or slowing down
the build process.
The demo included on disc's github page is the end result of running
the tool on browserify's own code base.
Command-Line Interface
Note: you'll need to build your bundle with the --full-paths flag for
disc to do its thing.
discify [bundle(s)...] {options}
Options:
-h, --help Displays these instructions.
-o, --output Output path of the bundle. Defaults to stdout.
When you install disc globally, you the discify command-line tool is
made available as the quickest means of checking out your bundle. As
of disc v1.0.0, this tool takes any bundled browserify script as input
and spits out a standalone HTML page as output.
For example:
browserify --full-paths index.js > bundle.js
discify bundle.js > disc.html
open disc.html
Last but not least, when you import your modules, avoid to entirely load the module if you need only few functions of it, example:
Instead of this:
import { core, fp } from 'lodash'
make this:
import core from 'lodash/core'
import fp from 'lodash/fp'
I am looking for a simple guide to setting up server-side watching and compiling .less files in a folder using less.js and node.js. Bryan wrote about it in this post.
Unfortunately, the instructions to Server-side usage on lesscss.org are of a little avail to somebody who is new to node.js.
I have tried command line usage: $ lessc styles.less > styles.css.
I have also tried 'watchr' and 'watch-less' and it all works. However, I am looking for a pure node.js + less.js solution. I am sure there is somebody who will be able to plainly explain how to configure node.js and less.js to watch .less files in a folder. Thanks.
I have created demo project to show how it works. You can find it here https://github.com/corpix/watcherDemo
After clone enter project directory and execute npm install to install less Node.js module.
Try running index.js and change .less file into less_files/ directory, modified file will be compiled and placed into css_files/
Honestly, I have seen a lot of the same threads and answers.
If you are like me and don't want any more code bloat than you already have then just download a LESS app for Win/Mac/Nix and it will auto-compile every time you save your .less files.
I honestly think this would put less of a load on the server because you only need to upload your compiled and minified files at this point.
I wrote something that could be what you are looking for. The script will look for .less files in the watch folder and compile them into the output folder. All you need to do is specify the folder you want to watch and the output folder.
node less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT
https://github.com/jonycheung/Dead-Simple-LESS-Watch-Compiler
It skips watching files with names that starts with underscore or a period.
I wrote this for my development process but it should still work on a server. However, you may want to re-consider watching a folder for changes constantly on a live server. It's an expensive operation.
You can use supervisor with -e argument to provide extensions to watch:
nohup supervisor -e 'js|ejs|less' $APP_DIR/app.js 1>$APP_DIR/log/app.log 2>&1 &
echo $! > $APP_DIR/pid/app.pid;
Taken from node-startup script: https://github.com/chovy/node-startup
The simpler version of this command is:
supervisor -e 'js|ejs|less' app.js
I know this is an old post, but came up a few times when I was recently searching for the same thing.
I have forked and updated the code from jonycheung - and have submitted a merge request.
Update: jonycheung has accepted the merge request so his original code is now updated
In the mean time, the code can be found here:
https://github.com/mikestreety/Dead-Simple-LESS-Watch-Compiler
I have also been working on and developing a pure bash script which uses lessc, but does not require a node script to run:
https://github.com/mikestreety/less-watch
Maybe not direct answer. But here is my comment:
Usually we need this watch during the development phase, where we need to change the less file and see the result without the need of re-running the lessc command by every change in less file.
We do this by pure less.js in the in the our html. as below:
<link rel="stylesheet/less" href="/path/to/bootstrap.less">
<script src="/path/to/less.js"></script>
After the finalizing the development task. You need to run lessc only once.
During development your pages may take a liitle more time to load, But if your site is ajax base, and you add this to your template page, it will not be a big deal.
You can use less-watch-compiler to watch for .less files. You don't need a main file to watch just like grunt. Just install this plugin:
npm install -g less-watch-compiler
or
yarn global add less-watch-compiler
Usage:
less-watch-compiler [options] <source_dir> <destination_dir>
Basic example
root
└──src
│ └── main.less
│ └── aux.less
└──dist
└── main.css
The project can be compiled with the following command:
less-watch-compiler src dist main.less
Basic Example 2
less-watch-compiler.config.json
{
"watchFolder": "src",
"outputFolder": "dist",
"mainFile": "main.less"
}
The project can be compiled with the following command:
less-watch-compiler
Source.
I'm using coffeescript with --watch option to rebuild javascript on changes to .coffee files.
Is it safe to combine that with node-supervisor to restart Node on changes to the compiled javascript?
I'm worried it won't be robust because of atomicity when coffeescript is recompiling multiple files. node-supervisor could jump the gun and restart Node on detecting the first filesystem change. Is it robust enough to realize there were additional changes while it was busy restarting Node?
Is there a better way? Ideally I'd have only one filesystem watcher recompile my coffeescript and restart node.
Create a JavaScript launcher, i.e. run.js, like this:
require('coffee-script');
require('./launch');
Then run this file with supervisor and appropriate options:
supervisor -e "node|js|coffee" run.js
This worked well for me on Windows.
You can use nodemon, it even has a delay feature (to restart server after a number of seconds have passed), for example:
nodemon --debug ./server.coffee 80
Another good feature of nodemon is ignoring files, example:
# this is my ignore file with a nice comment at the top
/vendor/* # ignore all external submodules
/public/* # static files
./README.md # a specific file
*.css # ignore any CSS files too
Other than that, read the documentation on the github repo and watch this Nodetuts video about nodemon: http://nodetuts.com/tutorials/14-some-nodejs-tools.html
You can use supervisor with -x option set to coffee. This will enable it to run script with right executable:
supervisor -x coffee your-script.coffee
Inspired by Lemming's answer.
In some of my Cakefiles, such as the one for connect-assets, I do the watching myself and simply spawn coffee -co lib src each time something changes, then restart the server when that child process finishes. That gets around the atomicity issue. If every .coffee file changes at once (or if you upgrade the coffee runtime), all of the JS files will update at once as well.
My foreman centric solution looks like this:
Procfile.dev
web: ./node_modules/supervisor/lib/cli-wrapper.js -n exit server.js
watch: ./node_modules/iced-coffee-script/bin/coffee --watch --compile server.iced
and then merely foreman start -f Procfile.dev
Then gitignore the resulting .js files. I like this approach because it keeps a constantly-updating vanilla JS file alongside my .iced files, so I can doublecheck my work as I go (I definitely make mistakes in coffeescript that I might not in vanilla).