I have a problem with my gulp webserver. I have this gulp task:
gulp.task('serve', ['watch'], () => {
gulp.src('tmp')
.pipe(webserver({
livereload: true,
directoryListing: true,
open: true,
//defaultFile: 'index.html'
}));
});
When running gulp serve I am getting the following screen on localhost:8000:
It seems like that the webserver is serving the root directory of my project and not tmp folder, the odd thing is if I click the index.html I am redirected to http://localhost:8000/index.html which is the correct file (tmp/index.html and not /index.html).
I am using gulp-webserver for serving and live reload.
What did I do wrong?
Note: uncommenting the defaultFile doesn't help.
You can pass an object into directoryListing to adjust this setting.
.pipe(webserver({
directoryListing: {
enable: true,
path: 'tmp'
}
}));
Details:
https://github.com/schickling/gulp-webserver#options
open can be also a string.By providing a String you can specify the path to open (for complete path, use the complete url http://my-server:8080/public/) .
Try this
gulp.task('serve', ['watch'], () => {
gulp.src('./tmp')
.pipe(webserver({
livereload: true,
directoryListing: true,
open: true,
//defaultFile: 'index.html'
}));
});
Hello I try to create my own config. and its much working well but some times i when i change html code live reload is not working dont know why.
Any one can help with that?
var livereload = require('gulp-livereload');
gulp.task('reload-html',function(){
gulp.src('./*.html')
.pipe(livereload())
.pipe(notify({ message: 'Reload html task complete' }));
});
gulp.task('watch-files',function(){
livereload.listen();
gulp.watch('*.html',['reload-html'])
gulp.watch('assets/sass/**/*.scss',['sass']);
gulp.watch('assets/images/src/**/*',['images-min']);
});
Also I use live reload plugin for google chrome.
why you don't simply use gulp-connect?
Here's a pretty simple sample:
'use strict';
var gulp = require('gulp');
// Files to be considered on live reload
var files = ['index.html', 'style.css' ];
var connect = require('gulp-connect');
gulp.task('files', function() {
gulp.src(files).pipe(connect.reload());
});
gulp.task('watch', function() {
gulp.watch(files, ['files']);
});
gulp.task('connect', function() {
// Default port: 8000
connect.server({livereload: true});
});
gulp.task('default', ['connect', 'watch']);
With that you don't need any Chrome Plugin.
Here is the Gist.
Thought this is not a solution to your problem this is an alternate to using Live-reload.
Browser-sync is a very powerful tool that does what Livereload does and much more.
Below is a simple gulp[ task for browser-sync:
var gulp = require('gulp');
var browserSync = require('browser-sync').create();
// Static server
gulp.task('browser-sync', function() {
browserSync.init({
server: {
baseDir: "./"
}
});
});
// or...
gulp.task('browser-sync', function() {
browserSync.init({
proxy: "yourlocal.dev"
});
});
More about browser-sync at:
http://www.browsersync.io/
I'm trying to setup this configuration, but I need help. I'm trying to use: https://github.com/accordionpeas/grunt-mocha-require-phantom.
My structure:
build-dev/ <-- Generated by grunt
vendor/
js/
jquery.js
require.js
js/
model/
cache.js <-- File to be tested
tests/
cache.js <-- Test for a file
tests.js <-- like test-bootstrap.js
My gruntfile config is:
mocha_require_phantom:
devel:
options:
base: 'build-dev/js'
main: 'tests'
requireLib: '../vendor/js/require.js'
files: ['tests/**/*.js']
port: 3001
My tests.js (test-bootstrap.js) is:
require.config({
paths: {
jquery: '../vendor/js/jquery',
chai: '/node_modules/chai/chai'
},
baseUrl: '/'
});
mocha.setup({
ui: 'bdd'
});
require([testPathname], function() {
if (window.mochaPhantomJS) {
return mochaPhantomJS.run();
} else {
return mocha.run();
}
});
My tests/cache.js is:
define(['chai', 'model/cache'], function(chai, cache) {
var should;
should = chai.should();
return describe('test suite 1', function() {
return it('should work', function() {
return cache.test().should.be.equal(5);
});
});
});
The problem is it's not working. It can't load model/cache. I was trying to change baseUrl in tests.js (like test-bootstrap.js). I was also trying to change baseUrl in grunt. I was trying to add path: model: ../../js/model, but it was ignored.
I need to call for a model as model/cache, how do I have to set up things to make it work? Should I use another plugin - which one?
Edit: Fixed typos.
I'm creating an app that uses webpack-dev-server in development alongside react-router.
It seems that webpack-dev-server is built around the assumption that you will have a public entry point at one place (i.e. "/"), whereas react-router allows for an unlimited amount of entry points.
I want the benefits of the webpack-dev-server, especially the hot reloading feature that is great for productivity, but I still want to be able to load routes set in react-router.
How could one implement it such that they work together? Could you run an express server in front of webpack-dev-server in such a way to allow this?
You should set historyApiFallback of WebpackDevServer as true for this to work. Here's a small example (tweak to fit your purposes):
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
var port = 4000;
var ip = '0.0.0.0';
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
historyApiFallback: true,
}).listen(port, ip, function (err) {
if(err) {
return console.log(err);
}
console.log('Listening at ' + ip + ':' + port);
});
I set up a proxy to achieve this:
You have a regular express webserver that serves the index.html on any route, except if its an asset route. if it is an asset, the request gets proxied to the web-dev-server
your react hot entrypoints will still point directly at the webpack dev server, so hot reloading still works.
Let's assume you run webpack-dev-server on 8081 and your proxy at 8080. Your server.js file will look like this:
"use strict";
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./make-webpack-config')('dev');
var express = require('express');
var proxy = require('proxy-middleware');
var url = require('url');
## --------your proxy----------------------
var app = express();
## proxy the request for static assets
app.use('/assets', proxy(url.parse('http://localhost:8081/assets')));
app.get('/*', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
# -----your-webpack-dev-server------------------
var server = new WebpackDevServer(webpack(config), {
contentBase: __dirname,
hot: true,
quiet: false,
noInfo: false,
publicPath: "/assets/",
stats: { colors: true }
});
## run the two servers
server.listen(8081, "localhost", function() {});
app.listen(8080);
now make your entrypoints in the webpack config like so:
entry: [
'./src/main.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081'
]
note the direct call to 8081 for hotreload
also make sure you pass an absolute url to the output.publicPath option:
output: {
publicPath: "http://localhost:8081/assets/",
// ...
}
For anyone else that may still be looking for this answer. I put together a simple proxy bypass which achieves this without much hassle and the config goes into the webpack.config.js
I am sure there are much more elegant ways to test for local content using regex, but this works for my needs.
devServer: {
proxy: {
'/**': { //catch all requests
target: '/index.html', //default target
secure: false,
bypass: function(req, res, opt){
//your custom code to check for any exceptions
//console.log('bypass check', {req: req, res:res, opt: opt});
if(req.path.indexOf('/img/') !== -1 || req.path.indexOf('/public/') !== -1){
return '/'
}
if (req.headers.accept.indexOf('html') !== -1) {
return '/index.html';
}
}
}
}
}
If you're running webpack-dev-server using CLI, you can configure it through webpack.config.js passing devServer object and using the historyApiFallback option:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js"
},
devServer: {
historyApiFallback: true
}
}
This will redirect to index.html everytime it 404 is encountered.
NOTE: If you're using publicPath, you'll need to pass it to devServer too:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js",
publicPath: "admin/dashboard"
},
devServer: {
historyApiFallback: {
index: "admin/dashboard"
}
}
}
You can verify that everything is setup correctly by looking at the first few lines of the output (the part with "404s will fallback to: path").
For a more recent answer, the current version of webpack (4.1.1) you can just set this in your webpack.config.js like such:
const webpack = require('webpack');
module.exports = {
entry: [
'react-hot-loader/patch',
'./src/index.js'
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader','css-loader']
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true,
historyApiFallback: true
}
};
The important part is historyApiFallback: true. No need to run a custom server, just use the cli:
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js --mode development"
},
I'd like to add to the answer for the case when you run an isomorphic app (i.e. rendering React component server-side.)
In this case you probably also want to automatically reload the server when you change one of your React components. You do this with the piping package. All you have to do is install it and add require("piping")({hook: true}) somewhere in the beginning of you server.js. That's it. The server will restart after you change any component used by it.
This rises another problem though - if you run webpack server from the same process as your express server (as in the accepted answer above), the webpack server will also restart and will recompile your bundle every time. To avoid this you should run your main server and webpack server in different processes so that piping would restart only your express server and won't touch webpack.
You can do this with concurrently package. You can find an example of this in react-isomorphic-starterkit. In the package.json he has:
"scripts": {
...
"watch": "node ./node_modules/concurrently/src/main.js --kill-others 'npm run watch-client' 'npm run start'"
},
which runs both servers simultaneously but in separate processes.
historyApiFallback can also be an object instead of a Boolean, containing the routes.
historyApiFallback: navData && {
rewrites: [
{ from: /route-1-regex/, to: 'route-1-example.html' }
]
}
May be not in all cases, but seems the publicPath: '/' option in the devServer is easiest solution to fix deep routes issue, see: https://github.com/ReactTraining/react-router/issues/676
This worked for me: just simply add the webpack middlewares first and the app.get('*'... index.html resolver later,
so express will first check if the request matches one of the routes provided by webpack (like: /dist/bundle.js or /__webpack_hmr_) and if not, then it will move to the index.html with the * resolver.
ie:
app.use(require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
}))
app.use(require('webpack-hot-middleware')(compiler))
app.get('*', function(req, res) {
sendSomeHtml(res)
})
I have been working all day on trying to get my proxies set up in my Gruntfile. Here is my Gruntfile:
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
module.exports = function(grunt) {
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
connect:{
livereload: {
options: {
middleware: function (connect) {
return [proxySnippet];
}
}
},
options: {
port: 9000,
base: 'app',
keepalive: true,
livereload: true
},
proxies: [
{
context: '/public/api',
host: 'localhost',
port: 8182,
https: false,
rewrite: {
'^/public/api': ''
}
}
]
}
});
grunt.registerTask('server', ['less', 'configureProxies', 'connect', 'connect', 'watch', 'open:dev']);
};
When I run my grunt server I can only hit my proxy. If I try to just hit anything other than the proxy I get a 404. What is giving me this issue?
I also had a lot of trouble setting up a proxy using grunt-connect-proxy.
Digging in the source code of grunt-contrib-connect, I realized that it uses the nodeJs Connect framework behind the scene.
Internally the middleware option defaults to this function:
function (connect, options) {
var middlewares = [];
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
var directory = options.directory || options.base[options.base.length - 1];
options.base.forEach(function (base) {
// Serve static files.
middlewares.push(connect.static(base));
});
// Make directory browse-able.
middlewares.push(connect.directory(directory));
return middlewares;
}
Which basically adds the connect.static and the connect.directory middlewares to an array passed to the connect(middlewares) constructor.
Knowing that, we can make use of the proxy-middleware nodeJs package like this:
connect: {
server: {
options: {
port: 9002,
keepalive: true,
middleware: function (connect, options) {
// Proxy all requests to target the local application.
var proxyOptions = require('url').parse('http://localhost:8080/');
proxyOptions.route = '/api';
return [
require('proxy-middleware')(proxyOptions), // Include the proxy first.
connect.static(options.base), // Serve static files.
connect.directory(options.base) // Make empty directories browse-able.
];
}
}
}
}
Basically we are adding a middleware to the middleware array.
This new proxy middleware will translate any incoming request like http://localhost:9002/api/ into http://localhost:8080/