Rails + React + Webpack loading an image - ruby-on-rails

I'm using rails + webpack to compile a bundle.js file into the rails asset pipeline. I placed an image inside /app/assets/images called "main.png". How can I access this image inside a React component that's being bundled?
I'm using shakacode's react on rails gem. https://github.com/shakacode/react_on_rails
I then tried using webpack to process the image which it did successfully and placed the image next to the bundle.js file. I still get a 404 on the image.
I know I'm close, just have the publicPath wrong for the rails asset. This current setup gives a localhost:3000/webpack/main.png which isn't working with rails.
This is my webpack file:
const webpack = require('webpack');
const path = require('path');
const devBuild = process.env.NODE_ENV !== 'production';
const nodeEnv = devBuild ? 'development' : 'production';
config = {
entry: [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
'./app/Register.js',
],
output: {
filename: 'webpack-bundle.js',
path: '../app/assets/webpack',
publicPath: '/webpack/'
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
},
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv),
},
}),
],
module: {
loaders: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham',
},
{
test: /\.jsx?$/, loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(png|svg)$/i,
loaders: [
'file?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack?bypassOnDebug&interlaced=false'
]
}
],
},
};
module.exports = config;
if (devBuild) {
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map';
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
);
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}

After defining a loader properly, you can load your image with a require function, for example! For example, add near your imports:
const myImg = require('./assets/methods.png');
Then, in your component's render method:
<img src={myImg} />
That should work...

Related

Adding autoprefixer to webpack 2.2.1

I'm trying to add autoprefixer to webpack 2.2.1 and having issues seeing the prefixes.
I installed postcss-loader https://github.com/postcss/postcss-loader as this seems to be the listed way to handle postcss in webpack.
I'm currently using scss files which I'm importing into my react files.
example: import styles from '../../styles/header.scss';
This is handled in webpack using sass-loader.
I'm not getting any error with my setup but I'm also not seeing any autopre-fixing going on to my files ? I presume this only needs to be added in development not production ?
Here is my dev setup webpack config.
const path = require('path')
const webpack = require('webpack')
const ROOT_DIR = path.resolve(__dirname, '../app')
module.exports = {
devtool: 'eval',
entry: [
`${ROOT_DIR}/js/index`,
'webpack-hot-middleware/client'
],
output: {
path: path.resolve(__dirname, '../public'),
filename: 'bundle.js',
publicPath: '/public/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.DefinePlugin({
"config.ASSET_URL": JSON.stringify(process.env.ASSETS_URL),
"config.GA_TRACKING_ID": JSON.stringify(process.env.GA_TRACKING_ID)
})
],
module: {
loaders: [
{ test: /\.js?$/,
loader: 'babel-loader',
include: path.join(__dirname, '../app'),
exclude: /node_modules/
},
{ test: /\.scss?$/,
include: path.join(__dirname, '../app', 'styles'),
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: { plugins: [
require('autoprefixer')
] }
},
{
loader: 'sass-loader',
options: {
data: "$assetPath: '" + process.env.ASSETS_URL + "';"
}
}
]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
include : path.join(__dirname, '../app', 'images'),
loader : 'file-loader?limit=30000&name=[name].[ext]'
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
include : path.join(__dirname, '../app', 'fonts'),
loader: 'file-loader?name=fonts/[name].[ext]'
}
]
}
}
I had a to deal with sometime similar recently. Check if it works if you create a separate postcss.config.js file in the directory of your scss files with this in it
//postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
and in your webpack config
{ test: /\.scss?$/,
include: path.join(__dirname, '../app', 'styles'),
use: [
{loader: "style-loader"},
{loader: "css-loader"},
{loader: "postcss-loader"},
{loader: "sass-loader",
options: {
data: "$assetPath: '" + process.env.ASSETS_URL + "';"
}
}
]
},

React on Rails with server side rendering

I created a site using React on Rails. It works perfectly fine, but I have not noticed that server side rendering is turned off, and I need it for SEO so I decided to turn it on. The thing is that now I get an error like this:
ERROR in SERVER PRERENDERING
Encountered error: "ReferenceError: window is not defined"
My webpack.config.js looks like this:
/* eslint comma-dangle: ["error",
{"functions": "never", "arrays": "only-multiline", "objects":
"only-multiline"} ] */
const webpack = require('webpack');
const path = require('path');
const devBuild = process.env.NODE_ENV !== 'production';
const nodeEnv = devBuild ? 'development' : 'production';
const bundles = [
'./app/bundles/Home/startup/registration'
]
const config = {
entry: [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
...bundles
],
output: {
filename: 'webpack-bundle.js',
path: '../app/assets/webpack',
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
},
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv),
},
}),
],
module: {
loaders: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham',
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
],
},
};
module.exports = config;
if (devBuild) {
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map';
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
);
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}
What should I do to fix it? I read through one of the realted issues on react_on_rails github but I still do not know.

How to load image by using webpack in .Net MVC

Currently using web pack in .net MVC with Angular 2 development. Hope someone can identify and explain what I have done wrong in the config.
Problem.
Unable to load images (404), check in browser and only 2 images being loaded.
In my project images folder,
webpack.config.js
var isDevBuild = process.argv.indexOf('--env.prod') < 0;
var path = require('path');
var webpack = require('webpack');
var nodeExternals = require('webpack-node-externals');
var merge = require('webpack-merge');
var allFilenamesExceptJavaScript = /\.(?!js(\?|$))([^.]+(\?|$))/;
// Configuration in common to both client-side and server-side bundles
var sharedConfig = {
resolve: { extensions: [ '', '.js', '.ts' ] },
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
loaders: [
{ test: /\.ts$/, include: /ClientApp/, loader: 'ts', query: { silent: true } },
{ test: /\.html$/, loader: 'raw' },
{ test: /\.css$/, loader: 'to-string!css' },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'url', query: { limit: 25000 } }
]
}
};
// Configuration for client-side bundle suitable for running in browsers
var clientBundleConfig = merge(sharedConfig, {
entry: { 'main-client': './ClientApp/boot-client.ts' },
output: { path: path.join(__dirname, './wwwroot/dist') },
devtool: isDevBuild ? 'inline-source-map' : null,
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [] : [
// Plugins that apply in production builds only
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
])
});
// Configuration for server-side (prerendering) bundle suitable for running in Node
var serverBundleConfig = merge(sharedConfig, {
entry: { 'main-server': './ClientApp/boot-server.ts' },
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist')
},
target: 'node',
devtool: 'inline-source-map',
externals: [nodeExternals({ whitelist: [allFilenamesExceptJavaScript] })] // Don't bundle .js files from node_modules
});
module.exports = [clientBundleConfig, serverBundleConfig];
webpack.config.vendor.js
var isDevBuild = process.argv.indexOf('--env.prod') < 0;
var path = require('path');
var webpack = require('webpack');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCSS = new ExtractTextPlugin('vendor.css');
module.exports = {
resolve: {
extensions: ['', '.js']
},
module: {
loaders: [
{ test: /\.(png|jpg|ico|gif|woff|woff2|eot|ttf|svg)(\?|$)/, loader: 'url-loader' },
{ test: /\.css$/, loader: extractCSS.extract("style-loader", "css-loader") }
]
},
entry: {
vendor: [
'#angular/common',
'#angular/compiler',
'#angular/core',
'#angular/http',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
'#angular/router',
'#angular/platform-server',
'angular2-universal',
'angular2-universal-polyfills',
'animate.css/animate.min.css',
'bootstrap',
'bootstrap/dist/css/bootstrap.min.css',
'bootstrap/dist/js/bootstrap.min.js',
'es6-shim',
'es6-promise',
'font-awesome/css/font-awesome.min.css',
'html5shiv',
'isotope-layout',
'jquery',
'wowjs/dist/wow.min.js',
'zone.js',
'./js/main.js',
'./js/respond.min.js',
'./css/main.css',
'./css/prettyPhoto.css',
'./css/responsive.css'
],
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
publicPath: '/',
filename: '[name].js',
library: '[name]_[hash]'
},
plugins: [
extractCSS,
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DllPlugin({
path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'),
name: '[name]_[hash]'
})
, new CopyWebpackPlugin([{ from: 'images', to: './images' }])
].concat(isDevBuild ? [] : [
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } })
])
};
_Layout.cshtml

Accessing webpack assets from rails app

I'm using webpack with React on Rails and have some react components that need to reference images.
The problem I'm having is trying to get Rails to access the images. Rails has its images served from its usual app/assets/images directory which is accessed via the url /assets
If however I have a react component and an image in an image directory:
component.js
images/image.jpg
+--component.js
+--images/image.jpg
If I try to reference the image by its relative path within component.js eg When I load the page in rails the page tries to access the url http://localhost:3000/home/images/image.jpg and not the url that rails expects the assets to be http://localhost:3000/assets/images/image.jpg
Does anyone know how to correct this?
This is my webpack.config
const webpack = require('webpack')
const path = require('path')
const devBuild = process.env.NODE_ENV !== 'production'
const nodeEnv = devBuild ? 'development' : 'production'
const config = {
entry: [
'whatwg-fetch',
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
'./app/bundles/index.js'
],
output: {
filename: 'webpack-bundle.js',
path: '../app/assets/webpack'
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom')
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv)
}
})
],
module: {
loaders: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham'
},
{
test: /\.(jpe?g|png|gif|svg|ico)$/, loader: 'file-loader'
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
}
}
module.exports = config
if (devBuild) {
console.log('Webpack dev build for Rails') // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map'
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
)
console.log('Webpack production build for Rails') // eslint-disable-line no-console
}

How do I fix this webpack deploy error on heroku?

When trying to deploy a react_on_rails app to heroku. I get a series of the following errors. Everything works fine locally, however when I try to deploy to heroku I get:
ERROR in ./app/bundles/appbundle/startup/MyApp.jsx
remote: Module not found: Error: Cannot resolve 'file' or 'directory' /tmp/build_5f0499a33a66627b6911c88bcf69f8ab/client/node_modules/react in /tmp/build_5f0499a33a66627b6911c88bcf69f8ab/client/app/bundles/appbundle/startup
The error seems straight forward, but I don't understand why it is not finding the files. It finds them perfectly fine on my local machine, so I don't understand what is wrong.
const webpack = require('webpack')
const path = require('path')
const glob = require('glob')
const devBuild = process.env.NODE_ENV !== 'production'
const nodeEnv = devBuild ? 'development' : 'production'
const config = {
entry: [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill'
].concat(glob.sync('./app/bundles/**/startup/*')),
output: {
filename: 'webpack-bundle.js',
path: '../app/assets/webpack'
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom')
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv)
}
})
],
module: {
loaders: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham'
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
}
}
module.exports = config
if (devBuild) {
console.log('Webpack dev build for Rails') // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map'
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
)
console.log('Webpack production build for Rails') // eslint-disable-line no-console
}

Resources