Use fs module in React.js, node.js, webpack, babel, express

I have a requirement in which I view the view in which I display the form. When submitting the form, I need to collect the form data and create a file and save the form data as JSON in this file. I use React.js, node.js, babel and webpack.

After the battle for this, I realized that I needed to use isomorphic or universal javascript. I use server-side response and rendering, since we cannot use the fs module on the client side. Refers to the server side .

Run it using: npm run start

After that, I see in the console that [Object Object] is printed to the console from line 1 in the component below the responsive component (HomePage.js). But later, when I access this page, I get an error message:

'bundle.js: 18 Unfixed error: could not find module' fs ''

How can I use the fs module with the answer?

The following are snippets of code:

webpack.config.js

 "use strict"; const debug = process.env.NODE_ENV !== "production"; const webpack = require('webpack'); const path = require('path'); module.exports = { devtool: debug ? 'inline-sourcemap' : null, entry: path.join(__dirname, 'src', 'app-client.js'), devServer: { inline: true, port: 3333, contentBase: "src/static/", historyApiFallback: true }, output: { path: path.join(__dirname, 'src', 'static', 'js'), publicPath: "/js/", filename: 'bundle.js' }, module: { loaders: [{ test: path.join(__dirname, 'src'), loader: ['babel-loader'], query: { //cacheDirectory: 'babel_cache', presets: debug ? ['react', 'es2015', 'react-hmre'] : ['react', 'es2015'] } }] }, plugins: debug ? [] : [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) }), new webpack.optimize.DedupePlugin(), new webpack.optimize.OccurenceOrderPlugin(), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, mangle: true, sourcemap: false, beautify: false, dead_code: true }), ] }; 

package.json

 { "name": "sample", "version": "1.0.0", "description": "Simple application to showcase how to achieve universal rendering and routing with React and Express.", "main": "src/server.js", "scripts": { "start": "SET NODE_ENV=production&&babel-node src/server.js", "start-dev": "npm run start-dev-hmr", "start-dev-single-page": "node_modules/.bin/http-server src/static", "start-dev-hmr": "webpack-dev-server --progress --inline --hot", "build": "SET NODE_ENV=production&&webpack -p" }, "dependencies": { "babel-cli": "^6.11.4", "babel-core": "^6.13.2", "babel-loader": "^6.2.5", "babel-plugin-react-html-attrs": "^2.0.0", "babel-preset-es2015": "^6.13.2", "babel-preset-react": "^6.11.1", "babel-preset-react-hmre": "^1.1.1", "ejs": "^2.5.1", "express": "^4.14.0", "react": "^15.3.1", "react-dom": "^15.3.1", "react-router": "^2.6.1" }, "devDependencies": { "http-server": "^0.9.0", "react-hot-loader": "^1.3.0", "webpack": "^1.13.2", "webpack-dev-server": "^1.14.1" } } 

server.js

 use strict'; import path from 'path'; import { Server } from 'http'; import Express from 'express'; import React from 'react'; import { renderToString } from 'react-dom/server'; import { match, RouterContext } from 'react-router'; import routes from './routes'; import NotFoundPage from './components/NotFoundPage'; //import fs from 'fs'; //console.log("server" + fs); // initialize the server and configure support for ejs templates const app = new Express(); const server = new Server(app); app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); // define the folder that will be used for static assets app.use(Express.static(path.join(__dirname, 'static'))); // universal routing and rendering app.get('*', (req, res) => { match( { routes, location: req.url }, (err, redirectLocation, renderProps) => { //console.log("renderProps "+ Object.values(routes)); //console.log("req.url "+ req.url); // in case of error display the error message if (err) { return res.status(500).send(err.message); } // in case of redirect propagate the redirect to the browser if (redirectLocation) { return res.redirect(302, redirectLocation.pathname + redirectLocation.search); } // generate the React markup for the current route let markup; if (renderProps) { // if the current route matched we have renderProps markup = renderToString(<RouterContext {...renderProps}/>); } else { // otherwise we can render a 404 page markup = renderToString(<NotFoundPage/>); res.status(404); } // render the index template with the embedded React markup return res.render('index', { markup }); } ); }); // start the server const port = process.env.PORT || 3000; const env = process.env.NODE_ENV || 'production'; console.log(`Server starting on http://localhost:${port} [${env}]`) server.listen(port, err => { if (err) { return console.error(err); } console.info(`Server running on http://localhost:${port} [${env}]`); }); 

HomePage.js (React component)

 import React from 'react'; import fs from 'fs'; import dateformat from 'dateformat'; console.log("home page" + fs); -- Line 1 class HomePage extends React.Component{ checkDirectory(directory, callback) { fs.stat(directory, function(err, stats) { //Check if error defined and the error code is "not exists" if (err && err.errno === 34) { //Create the directory, call the callback. fs.mkdir(directory, callback); } else { //just in case there was a different error: callback(err) } }); } handleClick(){ var obj = JSON.stringify($('#statusForm').serializeArray()); this.checkDirectory("directory/"+currentDate, function(error) { if(error) { console.log("oh no!!!", error); } else { //Carry on, all good, directory exists / created. fs.writeFile("directory/"+currentDate+name+".json", obj, function(err) { if(err) { return console.log(err); } console.log("The file was saved!"); }); console.log("exists"); } });*/ } render() { return ( <div className="container"> <form id="statusForm" className="form-horizontal" > <div className="form-group"> <label className="control-label col-sm-2" for="names">Select list:</label> <div className="col-sm-10"> <select name="names" className="form-control" id="names"> <option>Select</option> <option>abc</option> <option>xyz</option> </select> </div> </div> <div className="form-group"> <label className="control-label col-sm-2" for="team">Select list:</label> <div className="col-sm-10"> <select name="team" className="form-control" id="team"> <option>Select</option> <option>team 1</option> <option>team 2</option> </select> </div> </div> <div className="form-group"> <label className="control-label col-sm-2" for="pwd">Password:</label> <div className="col-sm-10"> <input type="textarea" className="form-control" id="todayTask" name="todayTask" placeholder="Enter Task"/> </div> </div> <div className="form-group"> <div className="col-sm-offset-2 col-sm-10"> <button type="button" className="btn btn-default" onClick={this.handleClick.bind(this)}>Submit</button> </div> </div> </form> </div> ); } } export default HomePage; 

EDIT 1:

I researched more and found out that if I don't create my application explicitly using npm run build and just update my reaction component, I don't get the above error. In addition, after that, if I put the logic of creating the file directly inside the visualization method, and on the refreshing page he successfully created the file. Therefore, observing this does not work with the Onclick button and may work if we refresh the page. it goes to the server and therefore works this way.

EDIT 2:

The page refresh issue was fixed with the target: 'node' in my webpack configuration, but I get an error:

Untrained ReferenceError: require not defined

In the logic of creating the file browser.so directly inside the render method will create the file at the moment of access to the page. No update required.

Can someone point me to what is the best way to achieve my desired requirement?

+7
javascript reactjs webpack isomorphic-javascript
source share
1 answer

Mistakes

First we mix up your mistakes a bit:

If you do not use npm run build or npm run start , you will not use webpack, and therefore the require statement will not be replaced by the contents of the fs module - instead, you are left with a requirement that your browser does not understand, since require is a Node function - only . Thus, your error does not require a definition.

If you start using npm run build or npm run start , webpack accepts this request and replaces it with the fs module. But, as you have discovered, fs does not work on the client side.

Alternatives

So, if you cannot use fs to save files, what can you do?

If you are trying to save a file on the server, you need to send data from the form to the Node server, and the Node server can use fs to interact with the server file system to save the file.

If you are trying to save the form locally, that is, on the same device as the browser, you need to use a different strategy, for example, or using the -side library client, for example FileSaver . Which option you use depends on your use case, but if you are trying to save on the client side, you can search for โ€œsave files from the web browserโ€ or โ€œsave the client side of filesโ€ to see what works for you.

+2
source share

All Articles