How to prevent Webpack from running several times from Makefile recipes - makefile

This is, presumably, more a make than a webpack question.
I'm using good ol' make to manage dependencies and builds, and webpack for building JS components. Example:
Makefile:
foo.js: src/foo.js
webpack -p
bar.js: src/bar.js
webpack -p
webpack.config.js:
var webpack = require('webpack');
module.exports = {
entry: {
'foo': './src/foo.js',
'bar': './src/bar.js',
},
output: {
path: './',
filename: '[name].js',
}
};
Quite obviously, every time when any of src/{foo,bar}.js changes, Webpack runs and builds both files. This might not be fixable, as I've read that this is on purpose (to cater for possible interactions between the modules).
However, when both change, Webpack will run twice, because the recipes don't know of each other. This is unnecessary and gets out of hand quickly.
Is there any possibility to "collect" the files and make Webpack only run once, independently of how many source files changed?

You could specify the entry point from the command line:
foo.js: src/foo.js package.json
webpack -p --entry src/foo.js
bar.js: src/bar.js package.json
webpack -p --entry src/bar.js

This answer set me on the right track. GNU Make runs recipes of so-called pattern rules only once. So changing my Makefile to this does the trick of running Webpack exactly once:
foo.j% bar.j%:
webpack -p
foo.js: src/foo.js
bar.js: src/bar.js

Related

Executing shell command after Webpack post build

I have a Laravel project and as you know when you deploy your app everything in your public directory should be copied over to your htdocs or public_html directory to hide your application's code.
I am using webpack to build my react code and everything else and each time I change my javascript webpack does what I want, it sees I make a change and then it builds it.
However I want to add one additional command after it builds and that is to copy everything from the public directory into the correct directory in htdocs/public_html.
So far I read up on this question here Run command after webpack build
It works and I can get the echo to work but I'm not sure why cp isn't working. Echo works but how do I know what shell commands I can use?
I tried 'cp' and even 'copy-item' which is powershell, but none are working.
This is my plugin so far, I figured I needed to change the directory to be safe
before copying anything over but again, nothing is working.
mix.webpackConfig(webpack => {
return {
plugins: [
new WebpackShellPlugin({
onBuildStart: ['echo "Starting Build ..."'],
onBuildEnd: ["cd 'E:\\xammp\\apps\\FactorioCalculator'",
"cp '.\\public\\*' '..\\..\\htdocs\\FactorioCalculator\\' -f -r"]
})
]
};
});
You could always use the copyDirectory mix method. Just put something like the following at the bottom of your webpack.mix.js file:
mix.copyDirectory('public', '../../htdocs/FactorioCalculator/')
You might have to change your path to ..\\..\\htdocs\\FactorioCalculator\\ as per the path in your question (I only have my mac with me so I'm unable to test on my other machine).
To answer you original question, if you want to execute a command each time webpack finishes building you can use the mix.then() which takes a closure.

How transpile via IDE ES6 to ES5 (and React-JSX) with WebStorm on Win10 with Babel6?

A lot of sources explain that for this you need to
create a "File Watcher"-Job in the WebStorm-Settings (Tools)
define a "Scope" in WebStorm for the files you want to process
define a .babelrc file for configuration. Babel will use this automatically so you save some params in the call
{
"presets": ["es2015", "react"],
"plugins": ["transform-es2015-arrow-functions"]
}
npm install --save-dev the corresponding packages together with the babel-cli package.
BUT... how can I run the babel-Command on Windows when babel-cli module just delivers a "babel.js" file in its bin-folder? However Windows can only execute .exe, .bat or .cmd-files.
I tried to wrap the call in a cmd-script containing babel %* as I found a solution in one web article, but this did not work for me.
The solution for me was to fill the File Watcher form in a way to have the call of the node executable as Program and add the call for babel.js as first of the Arguments
Program: C:\Program Files\nodejs\node.exe
Arguments: $ProjectFileDir$/node_modules/babel-cli/bin/babel.js $FilePathRelativeToProjectRoot$ --source-maps --out-dir src/test/js
Working Directory: $ProjectFileDir$
Output paths to refresh: $ProjectFileDir$\src\test\js
This makes the babel.js callable for the File Watcher.

Webpack --watch does not work on Windows (nor webpack-dev-server)

It seems to be a common problem, but after a few days of active searching I didn't find any solution that works in my case.
windows7-x64
node: 6.3.0-x64 (also tried node-v4.4.7-x64)
npm: 3.10.3
webpack: 1.13.1
sublime text (not Vim)
First of all, I can't install fsevents on windows, which might be the problem, because it's the library for watching on OS X.
D:\file>npm install webpack
file#1.0.0 D:\file
`-- webpack#1.13.1
npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents#1.0.13
So, if your --watch works on windows, please tell me, do you have the same issue with skipping fsevents when installing webpack?
Secondly, webpack --watch does compile the file, but it doesn't watch at all.
E.g. if I use stylus watch, then it actually blocks my command line until I press ctrl+c
D:\file>stylus -w style.styl
watching C:/Users/...
compiled style.css
watching style.styl
_
And only after ctrl+c it will unblock my keyboard.
^CTerminate batch job (Y/N)? y
stylus-watch
While webpack -w is totally different. It's not just not compiling the file on changes, but it's also not watching at all. I mean that after typing the command webpack --watch it's compiling the file one time, but it doesn't lock my keyboard and so it allows me to write another command.
D:\webpa>webpack main.js bundle.js
D:\webpa>webpack -w main.js bundle.js
D:\webpa>webpack --watch main.js bundle.js
D:\webpa>
webpack-watch
The same with webpack-dev-server - it starts server, but then immediately finishes it.
D:\webpa>webpack-dev-server --hot --inline
http://localhost:8080/
webpack result is served from /
content is served from D:\webpa
D:\webpa>
It looks like the problem is not with webpack.config.js, because it doesn't watch even with a command like webpack --watch main.js bundle.js, but anyway, here is my basic config.
var webpack = require('webpack');
module.exports = {
context: __dirname,
entry: "./main.js",
output: {
path: __dirname,
filename: "bundle.js"
},
};
And I've tried many other variants:
var webpack = require('webpack');
var path = require('path');
var entry = path.join(__dirname, "main.js");
var WebpackNotifierPlugin = require('webpack-notifier');
module.exports = {
context: __dirname,
entry: entry,
output: {
path: __dirname,
filename: "bundle.js"
},
resolve: {root: [__dirname]},
resolve: { fallback: path.join(__dirname, "node_modules") },
resolveLoader: { fallback: path.join(__dirname, "node_modules") },
plugins: [
new webpack.OldWatchingPlugin(),
new WebpackNotifierPlugin(),
new webpack.ResolverPlugin(
new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
),
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors/js/applibs.js'),
new webpack.optimize.DedupePlugin()
]
};
As I said, the problem seems to be not in webpack.config.js
I've also tried things like:
echo fs.inotify.max_user_watches=524288
webpack-dev-server --content-base ./ --port 9966 --hot --inline
webpack --watch --watch-poll
rename/move/create new folder, reinstall node.js and webpack
So yeah, if you had this issue and you resolved it, please share some info.
Did you have problems with installing fsevents?
Was your webpack --watch command blocking your keyboard and actually watching, but just not compiling files after changes? Or was it finishing watching immediately like in my case?
Any other suggestions what to use apart from --watch and webpack-dev-server?
Thanks!
I'll include this here because it fixed my issue. It may or may not fix yours, depending on if your paths in your post are actually the paths you're using. If it doesn't resolve your issue, at least it'll solve somebodies cause this question comes up first thing for this issue.
You can't have a path with "(" or ")" in it, because the is-glob dependency thinks it's a glob if you do. If you must put your project in a path with "(" (like Program Files (x86)), then you must add something like this to your is-glob module in node_modules:
if (typeof str === 'string' && str.indexOf('Program Files (x86)') > -1)
return false
Have a look at using fswatch. I find myself in the same mess. Windows/Linux cannot support fsevents considering its strictly for OSX. Support for Linux, for example, is through inotify.
It seems fswatch provides a cross-platform filesystem monitor, so you should be all set if you use with your windows machine.

How to run mocha tests with webpack when you don't have a single entry point to tests?

I'm trying to convert a project from browserify+mochify to webpack.
The webpack docs demonstrate how to use mocha-loader to run the tests with webpack-dev-server, but assumes a single entry point into the tests.
All the existing tests were designed with mochify in mind which does not require a single entry point as it recursively bundles ./test/*.js.
The setup below sort of works for me. It still uses mochify to run the tests (because it has all the phantomjs interfacing), but doesn't rely on anything from browserify. If you run webpack --watch, it reruns all tests when a file changes.
webpack.config.js:
var path = require("path");
var child_process = require('child_process');
module.exports = {
entry: {
tests: "./tests.js"
},
output: {
filename: "tests.js", // Should be a unique name
path: "/tmp"
},
plugins: [
// Automatically run all tests when webpack is done
function () {
this.plugin("done", function (stats) {
child_process.execSync('mochify /tmp/tests.js', { stdio: 'inherit'});
});
}
],
};
tests.js:
// List all test dirs here if you have multiple
var contexts = [
require.context('./dir1/test', true, /\.js$/),
require.context('./dir2/test', true, /\.js$/)
];
contexts.forEach(function (context) {
context.keys().forEach(context);
});
Another approach is described here: https://stackoverflow.com/a/32386750/675011
This is not exactly an answer, but it solved the problem for me. The reason I wanted to combine mochify and webpack was that I wanted to use the browser console to debug my mocha tests. Since my mocha tests themselves don't rely on a browser, it was enough for me to finally realize I could use a node debugger and it would bring up the Chrome console, (almost) solving my problem. node-inspector is the node debugger, but I'm using babel, so I needed babel-node-debug, but that doesn't yet work with babel6, but there's an unmerged pull request that fixes it: https://github.com/CrabDude/babel-node-debug/pull/12.

How do use node-qunit?

The info on this page seems less-than-forth-coming -- https://github.com/kof/node-qunit. I've got a setup where I installed nodejs and installed the node-quit module. I have test runner and executed the command node /path/to/runner.js. Below is an example of my setup. Any ideas or examples on how to do this or maybe I'm using it wrong. I previous ran qunit tests using Rhino and EnvJs without any issues but I figured I try nodejs since I using it for other things and the packaging system can be scripted in my build. Maybe I missing an option to node to include Qunit or some environment variable not set -- that would make sense.
File Structure
node/
public/
js/
main.js
tests/
js/
testrunner.js
tests.js
Installation
cd node
npm install qunit
This will now update the file structure.
node/
node_modules/
qunit/
tests/js/testrunner.js
var runner = require("../../node/node_modules/qunit");
runner.run({
code : "/full/path/to/public/js/main.js",
tests : "/full/path/to/tests/js/tests.js"
});
tests/js/tests.js
test("Hello World", function() {
ok(true);
});
Command
node tests/js/testrunner.js
It appears that you need to use full paths to the main.js and tests.js files and also include a relative path to the qunit module. I updated the code above as an example for others.

Resources