How to pass process.env.NODE_ENV from Gulp to Webpack? - node.js

I have a gulpfile, where I create a webpackDevServer to live-update my js code. I set a process.env.NODE_ENV variable in gulpfile, but for some reason webpack doesn't see it - it is undefined.
Here's the relevant piece of my gulpfile.js:
gulp.task("watch", ["_set-env:dev"], function() {
// modify default webpack configuration for Development Server
var webpackDevConfig = Object.create(webpackConfig);
webpackDevConfig.devtool = "eval";
webpackDevConfig.debug = "true";
new webpackDevServer(webpack(webpackDevConfig), {
proxy: {
"/api/*": {target: "http://localhost:8000", secure: false},
"/static/*": {target: "http://localhost:8000", secure: false},
"/media/*": {target: "http://localhost:8000", secure: false}
}
}).listen(8001, "localhost", function (err) {
if (err) throw new gutil.PluginError("webpack-dev-server", err);
gutil.log("[webpack-dev-server]", "http://localhost:8001" + webpackDevConfig.output.publicPath);
});
});
gulp.task("_set-env:dev", function() {
gutil.log("set-env", "ENV => development");
genv({
vars: {
NODE_ENV: "development"
}
});
});
Then in webpack I check its value and it is undefined:
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
...
const environmentsFile = path.join(__dirname, "/environments.json");
const nodeModulesPath = path.join(__dirname, "/node_modules");
const bowerComponentsPath = path.join(__dirname, "/bower_components");
console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
console.log(process.env.NODE_ENV);
const webpackConfig = {
entry: {
app: ["app.js"]
},
And on the console I see:
$ gulp watch
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
undefined
[22:28:34] Using gulpfile ~/Documents/frontend/gulpfile.js
[22:28:34] Starting '_set-env:dev'...
[22:28:34] set-env ENV => development
[22:28:34] Finished '_set-env:dev' after 7.63 ms
[22:28:34] Starting 'watch'...

You probably have something like this close to the top of your gulpfile:
var webpackConfig = require('./webpack.config.js');
That means your webpack configuration is evaluated before the _set-env:dev task even runs. Remember: your gulpfile only defines tasks. The tasks themselves aren't run until after the entire gulpfile has been evaluated.
You need to defer requiring your webpack configuration until after the _set-env:dev task has run by deleting the line at the top of your gulpfile and putting the require() directly into your watch task:
gulp.task("watch", ["_set-env:dev"], function() {
// modify default webpack configuration for Development Server
var webpackDevConfig = Object.create(require('./webpack.config.js'));

Related

Can't resolve 'fs' in nextjs with custom express server

I add fs to my nextjs project and received the following error:
Module not found: Can't resolve 'fs' in '/Users/neven/Development/next-js/node_modules/dotenv/lib'
I found that to resolve this issue, I should add config.node = { fs: 'empty' } to my next.config.js file.
The problem is that when I add that config param, dotenv plugin stops working, that is env variables are not loaded on client side.
This is my next.config.js file, which works without any issues.
const withCSS = require('#zeit/next-css')
const dotenv = require('dotenv')
const path = require('path')
const Dotenv = require('dotenv-webpack')
dotenv.config()
module.exports = withCSS({
webpack: config => {
config.plugins = config.plugins || []
config.plugins = [
...config.plugins,
// Read the .env file
new Dotenv({
path: path.join(__dirname, '.env'),
systemvars: true,
}),
]
return config
},
})
And then when I add fs: 'empty', it looks like this:
const withCSS = require('#zeit/next-css')
const dotenv = require('dotenv')
const path = require('path')
const Dotenv = require('dotenv-webpack')
dotenv.config()
module.exports = withCSS({
webpack: config => {
config.plugins = config.plugins || []
config.node = {
fs: 'empty'
}
config.plugins = [
...config.plugins,
// Read the .env file
new Dotenv({
path: path.join(__dirname, '.env'),
systemvars: true,
}),
]
return config
},
})
Do you have any suggestions on how I could work this thing out?
Let me know in case additional details are needed.
I found out what the issue was; dotenv plugin is working correctly, but I was trying to get the variables on client side, and that is not possible in this way.
The solution to use env variables on client side is to add env: { EXAMPLE: 'helloWorld' } to next.config.js file.
const withCSS = require('#zeit/next-css')
const dotenv = require('dotenv')
const path = require('path')
const Dotenv = require('dotenv-webpack')
dotenv.config()
module.exports = withCSS({
env: { EXAMPLE: 'helloWorld' },
webpack: config => {
config.plugins = config.plugins || []
config.node = {
fs: 'empty'
}
config.plugins = [
...config.plugins,
// Read the .env file
new Dotenv({
path: path.join(__dirname, '.env'),
systemvars: true,
}),
]
return config
},
})
The issue here is that your client-side can't access the environment variables.
Started NextJS 9.4, you can use .env* files to add your environment variables.
For your client-side to get access access to the environment variables, you just need to prefix them with NEXT_PUBLIC_
NEXT_PUBLIC_YOUR_KEY="keykeykey"
These can be accessible with:
process.env.NEXT_PUBLIC_YOUR_KEY

webpack-dev-server inside express?

I´m trying to understand how to use webpack-dev-server for hot bundling and reloading and I got the following code from react-redux-universal-hot-example:
var Express = require('express');
var webpack = require('webpack');
var config = require('../src/config');
var webpackConfig = require('./dev.config');
var compiler = webpack(webpackConfig);
var host = config.host || 'localhost';
var port = (Number(config.port) + 1) || 3001;
var serverOptions = {
contentBase: 'http://' + host + ':' + port,
quiet: true,
noInfo: true,
hot: true,
inline: true,
lazy: false,
publicPath: webpackConfig.output.publicPath,
headers: {'Access-Control-Allow-Origin': '*'},
stats: {colors: true}
};
var app = new Express();
app.use(require('webpack-dev-middleware')(compiler, serverOptions));
app.use(require('webpack-hot-middleware')(compiler));
app.listen(port, function onAppListening(err) {
if (err) {
console.error(err);
} else {
console.info('==> Webpack development server listening on port %s', port);
}
});
Questions:
a) Why is this code calling var app = Express() to seutp an express server ? Isn´t it webpack-dev-server a server itself ?
b) From the webpack-dev-server I expected somthing like:
var WebpackDevServer = require("webpack-dev-server");
var webpack = require("webpack");
var fs = require("fs");
var compiler = webpack({
// configuration
});
var server = new WebpackDevServer(compiler, {
// webpack-dev-server options
}) ;
Why is react-redux-universal-hot-example doing it inside a new instance of express() ?
c) Is there any docs or tutorials of this type of webpack-dev-server usage ?
Thanks for helping - I´m confused here.
As far as you see your application require a pair of middlewares
app.use(require('webpack-dev-middleware')(compiler, serverOptions));
app.use(require('webpack-hot-middleware')(compiler));
It's just easier to set it up having express middleware system.
There is a good documentation with examples https://webpack.github.io/docs/webpack-dev-server.html

how to use ngnix to serve webpack build files in production

I wrote a vue + webpack project and it works fine in webpack-dev-middleware. Now I want to deploy it with nginx. What I do is write a webpack.build.config.js and bundle all files into a dist folder. Then I just copy the dist folder into nginx html folder and assign the index in nginx.conf. However, it has an error said:
[Vue warn]: Failed to mount component: template or render function not
defined. (found in root instance)
I am a newbie for devops/backend and quite confused with the overall build or deploy process. Is webpack-dev-server or nodejs still need in the production environment? My production environment backend is nginx/PHP and IIS/.Net, now it do not have node installed at all.
My nginx.conf is
location / {
root html/dist;
index index.html index.htm;
}
And the webpack.build.config.js is
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var public_dir = "components";
//var ModernizrWebpackPlugin = require('modernizr-webpack-plugin');
module.exports = {
entry: [
path.join(__dirname,'./index.js')
],
output: {
path: path.join(__dirname, '/dist/'),
filename: '[name].js',
publicPath: '/'
},
devtool: 'eval-source-map',
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js'),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.AggressiveMergingPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, 'index.html'),
inject: true
})
],
resolve: {
root: [path.resolve('./components')],
extensions: ['', '.js', '.css']
},
module: {
loaders: [
]
}
};
When build I run
webpack -p --config ./webpack.build.config.js
I'm using vue-cli to init vuejs webpack project. And the project already has build script, you can refer it:
require('./check-versions')()
process.env.NODE_ENV = 'production'
var ora = require('ora')
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
After built, we will have a dist folder. Upload all files inside to html folder of Nginx (default)
Config root path to use full path like this:
listen 80;
server_name mydomain www.mydomain;
root /var/www/html;

How can I set NODE_ENV?

I am using gulp in my reactjs solution and want to set the NODE_ENV, I tried this:
gulp.task('set-dev-node-env', function() {
return process.env.NODE_ENV = 'development';
});
//dev environment run
gulp.task('default', ['set-dev-node-env', 'webpack-dev-server']);
When I run gulp and check the chromeconsole it says:
testing process.env.NODE_ENV undefined
What am I missing or how can I set this NODE_ENV variable? I would like to set it in the gulpfile somehow.
Here is the complete project: github
Since you are using WebPack you can use the WebPack Define Plugin to inject the NODE_ENV
For example in your webpack.config.dev.js:
module.exports = {
...
plugins: [
...
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'),
}),
],
};
Then in your react code you will have access to it NODE_ENV you set as process.env.NODE_ENV.
You can try this using gulp-env module
// gulpfile.js
var gulp = require('gulp');
var env = require('gulp-env');
gulp.task('set-dev-node-env', function () {
env({
vars: {
NODE_ENV: "development"
}
})
});
gulp.task('default', ['set-dev-node-env', 'webpack-dev-server'])

RequireJs Module in node always returns undefined when using in a grunt task

I've a small config file that I need in frontend and in my grunt task.
js/config.js:
define(function() {
return [
{
id: 'demo',
displayName: 'Demo'
}
];
});
I can load the file in frontend without problems it also work in node.
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
var config = requirejs('config')
But when I try to load the same file in a grunt task it returns undefined:
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
grunt.registerTask('lala', function () {
var config = requirejs('config')
});
The problem was that the I require requireJs outside of the module.exports function. So this works after all:
module.exports = function(grunt) {
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js/cfe/app/platforms/as'
});
grunt.registerTask('lala', function () {
var config = requirejs('config')
});
}
This code works for me. First I've installed requirejs:
cd /path/to/code/directory
npm install requirejs
Then in my app.js:
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
var config = requirejs('config');
console.log(config);
And in the js/config.js:
define(function() {
return [
{
id: 'demo',
displayName: 'Demo'
}
];
});
When I run it, I get the correct result:
$ node app.js
[ { id: 'demo', displayName: 'Demo' } ]
I'm using Node v0.10.1.

Resources