For clarification - this is a question about writing a webpack plugin
How do you use the webpack require inside a webpack plugin?
MyPlugin.prototype.apply = function(compiler) {
var self = this;
compiler.plugin('emit', function(compilation, callback) {
var file = 'example.css';
compilation.fileDependencies.push(file);
var loaderResult = require('style!css!' + file); // <-- is there any way to make this possible?
});
};
After some searching I saw that the text-extract plugin uses a child compilation to use a compiler inside the plugin:
https://github.com/SanderSpies/extract-text-webpack-plugin/blob/be6484f00c46799280b9ec28946faf935cb9ae63/loader.js#L65
In the following example I am using the my-loader to load and compile the input.js file:
MyPlugin.prototype.apply = function(compiler) {
compiler.plugin('make', function(compilation, callback) {
var outputOptions = {
filename: 'output.js',
publicPath: compilation.outputOptions.publicPath
};
var childCompiler = compilation.createChildCompiler('MyPluginCompilation', outputOptions);
childCompiler.apply(new NodeTemplatePlugin(outputOptions));
childCompiler.apply(new LibraryTemplatePlugin('result', 'var'));
childCompiler.apply(new NodeTargetPlugin());
childCompiler.apply(new SingleEntryPlugin(this.context, 'my-loader!input.js'));
childCompiler.runAsChild(callback);
});
};
Related
I added a self written WebSocket-Client library. When I require in node.js it works fine, just as in Node-RED's function-node with registering it in settings.js and requireing it by global.get("RWSjs").
Now I had to write a Node by myself and wanted to require this file, and it doesn't work. Node-RED always gives me the "node not deployed" error, which is, I think, because of a javascript syntax error.
How can I require a self written module in a self written node's .js?
Thanks a lot in advance, Peter :)
Edit:
some Code:
eval-R-char.js (Code for the node)
module.exports = function(RED) {
// doesn't work:
var RWSjs = global.get("RWSjs");
function EvalRCharNode(config) {
RED.nodes.createNode(this,config);
this.instruction = config.instruction;
var node = this;
this.on('input', function(msg) {
//msg.payload = msg.payload.toLowerCase();
msg.payload = "Instruction: " + this.instruction;
node.send(msg);
});
}
RED.nodes.registerType("eval-R-char",EvalRCharNode);
}
You shouldn't use the context to require modules when writing your own nodes, it is purely a workaround as you can't use require in the function node.
You should just require as normal in your custom node.
So in this case:
module.exports = function(RED) {
//assuming your module is in the RWS.js file in the same directory
var RWSjs = require('./RWS.js');
function EvalRCharNode(config) {
RED.nodes.createNode(this,config);
this.instruction = config.instruction;
var node = this;
this.on('input', function(msg) {
//msg.payload = msg.payload.toLowerCase();
msg.payload = "Instruction: " + this.instruction;
node.send(msg);
});
}
RED.nodes.registerType("eval-R-char",EvalRCharNode);
}
After some research on the benefits of the isomorphic/universal javascript apps and server side rendering I have decided to use it in a project.
I am using Express.js and React.js to achieve server side and client side rendering.
One problem I have faced recently is my browser javascript cannot find a React variable which is a React component. It gives the error message of well known ReferenceError: Can't find variable: QuestionBox.
This react component is defined in the questionbox.js and this file used for server side after transpiled by babel in node.js and for client side rendering after browserifyed and rectifyed in a gulp task.
What can be the point here I am missing? It can be the gulp generated transformed file that is loaded by the browser by a script tag. The full code is in this gist.
questionbox.js:
var React = require('react');
var marked = require('marked');
/*
-QuestionBox
-QuestionList
-Question
*/
var Question = React.createClass({//Omitted here for simplicity: https://gist.github.com/isikfsc/b19ccb5e396fd57693d2f5b876ea20a0});
var QuestionList = React.createClass({//Omitted here for simplicity: https://gist.github.com/isikfsc/b19ccb5e396fd57693d2f5b876ea20a0});
var QuestionBox = React.createClass({
loadQuestionsFromServer: function() {
return true;
},
getInitialState: function() {
return {data: []};
},
componentWillMount: function() {
this.loadQuestionsFromServer();
setInterval(this.loadQuestionsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="questionBox">
<h1>Questions</h1>
<QuestionList data={this.state.data} />
</div>
);
}
});
module.exports.QuestionBox = QuestionBox;
gulpfile.js:
var gulp = require('gulp');
var browserify = require('browserify');
var watchify = require('watchify');
var source = require('vinyl-source-stream');
var reactify = require('reactify');
var production = process.env.NODE_ENV === 'production';
function scripts(watch) {
var bundler, rebundle;
bundler = browserify('src/components/questionbox.js', {
basedir: __dirname,
debug: !production,
cache: {}, // required for watchify
packageCache: {}, // required for watchify
fullPaths: watch // required to be true only for watchify
});
if(watch) {
bundler = watchify(bundler)
}
bundler.transform(reactify);
rebundle = function() {
var stream = bundler.bundle();
//stream.on('error', handleError('Browserify'));
stream = stream.pipe(source('bundle.js'));
return stream.pipe(gulp.dest('./dist/components'));
};
bundler.on('update', rebundle);
return rebundle();
}
gulp.task('watchScripts', function() {
gulp.watch('./src/components/*.js', ['scripts']);
});
gulp.task('scripts', function() {
return scripts(false);
});
gulp.task('watchScripts', function() {
return scripts(true);
});
I believe the problem is that the component is not (and really should not be) exposed to the global scope.
All the code inside the browserify bundle in not accessible from outside. So what should be done next is moving render function into the bundle.
To begin with, you can create new file (say, entry.js) and set it as an entry point for browserify in gulpfile.js:
bundler = browserify('src/entry.js', {
Then, You could move JavaScript from the template (.ejs) to this entry point.
var ReactDOM = require('react-dom');
var QuestionBox = require('./components/questionbox.js').QuestionBox;
ReactDOM.render(QuestionBox({}), document.getElementById('mount-node'));
As long as browserify bundle is only used by the client, You don't have to change anything on the server.
I have the following task in gulp and I need to ADD at the beginning of my concatenated file (testApp.css) some text for copyright information.
How to achieve it in gulp?
gulp.task('flat', function () {
gulp.src(['themes/**/*.styl', '!themes/**/**mixins**.styl', '!themes/**/**variables**.styl'])
.pipe(stylus({
compress: true,
use: nib()
}))
.pipe(concat('testAll.css'))
.pipe(gulp.dest('testx'));
});
You can use prepend with gulp-insert
npm install gulp-insert
Used in combination with fs:
var fs = require('fs');
var insert = require('gulp-insert');
var copyright = function () {
return fs.readFileSync('copyright.txt');
};
gulp.task('flat', function () {
gulp.src(['themes/**/*.styl', '!themes/**/**mixins**.styl', '!themes/**/**variables**.styl'])
// Your other stuff
.pipe(insert.prepend(copyright));
.pipe(gulp.dest('testx'));
});
Check it out on GitHub for more information.
I was able to solve my issue using gulp-header. Suggestion for other suitable plugins are welcome.
var stylus = require('gulp-stylus');
var nib = require('nib');
var concat = require('gulp-concat');
var header = require('gulp-header');
var fs = require('fs');
gulp.task('flat', function () {
gulp.src(['themes/**/*.styl', '!themes/**/**mixins**.styl', '!themes/**/**variables**.styl'])
.pipe(stylus({
compress: true,
use: nib()
}))
.pipe(concat('testAll.css'))
.pipe(header(fs.readFileSync('copyright.txt', 'utf8')))
.pipe(gulp.dest('test'));
});
I'm trying to render each file in my gulp source files with it's own json file, but I can't figure out how to access the current filename in the pipe function.
var gulp = require('gulp');
var handlebars = require('handlebars');
var gulpHandlebars = require('gulp-compile-handlebars');
gulp.task('compile-with-sample-data', function () {
var options = {}
return gulp.src('./src/**/*.html')
.pipe(gulpHandlebars({ data: require('./data/' + filename +'.json') }, options))
.pipe(gulp.dest('./build/'));
});
Where I can get it to work with the same file each time by just using require('./data/orders-complete.json'):
var gulp = require('gulp');
var handlebars = require('handlebars');
var gulpHandlebars = require('gulp-compile-handlebars');
gulp.task('compile-with-sample-data', function () {
var options = {}
return gulp.src('./src/**/*.html')
.pipe(gulpHandlebars({ data: require('./data/orders-complete.json') }, options))
.pipe(gulp.dest('./build/'));
});
It's not clear how I would do this.
Use gulp-tap, it enables you to get the file name and even change it for downstream pipes.
I am creating my first application in Phonegap. I have made some plugin like FileOpener, Downloader and stausBarNotification. Plugins are like this:
FileOpener.js is like this:
cordova.define("cordova/plugin/fileopener",
function(require, exports, module) {
var exec = require("cordova/exec");
var FileOpener = function () {};
FileOpener.prototype.open = function(url) {
exec(null, null, "FileOpener", "openFile", [url]);
};
var fileOpener = new FileOpener();
module.exports = fileOpener;
});
/**
* Load Plugin
*/
if (!window.plugins) {
window.plugins = {};
}
if (!window.plugins.fileOpener) {
window.plugins.fileOpener = cordova.require("cordova/plugin/fileopener");
}
Downloader.js is like this:
cordova.define("cordova/plugin/downloader",
function(require, exports, module) {
var exec = require("cordova/exec");
var Downloader = function () {};
Downloader.prototype.downloadFile = function(fileUrl, dirName, fileName, overwrite, win, fail) {
navigator.notification.alert('url: '+fileUrl+' to dir: '+dirName + ' to file: '+fileName);
if (overwrite == false)
overwrite = "false";
else
overwrite = "true";
exec(win, fail, "Downloader", "downloadFile", [ fileUrl, dirName, fileName, overwrite ]);
};
var downloader = new Downloader();
module.exports = downloader;
});
if (!window.plugins) {
window.plugins = {};
}
if (!window.plugins.downloader) {
window.plugins.downloader = cordova.require("cordova/plugin/downloader");
}
And I have have made some java file to implement is as well. Now it is running as expected in android device. But now I want a same project for for ios and I want build.phonegap.com will do that for me.
I have include the plugin in config.xml like this:
<gap:plugin name="FileOpener" value="com.phonegap.plugins.fileOpener.FileOpener"/>
<gap:plugin name="Downloader" value="com.phonegap.plugins.downloader.Downloader"/>
<gap:plugin name="StatusBarNotification" value="com.phonegap.plugins.statusBarNotification.StatusBarNotification"/>
Now where to go from here? I have read some articles which is telling me to submit the plugin to phonegap.com how will i do this? Will the project run same as android device in iPhone? Thanks for any help in advance.
In order to submit your plugin, follow the documentation found at https://build.phonegap.com/docs/plugins-contributing. Once submitted, it will be reviewed and made available to the public. You can see a list of available plugins at https://build.phonegap.com/plugins