I want to be able to use import in my react application for not only js/jsx files but also for css files. From what I've read, the best way to do that is to use the extract-text-webpack-plugin which will take your imported css files and bundle them together.
I've set it up so that its generating my bundled css file, but for some reason every time I load my page I get a syntax error:
SyntaxError: MyWebpage/views/global.css: Unexpected token, expected ; (1:5)
> 1 | body {
| ^
2 | margin: 0;
3 | }
My setup looks like this:
webpack.config.js
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const config = {
entry: ['babel-polyfill', './views/Index.jsx'],
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/public'
},
module: {
rules: [
{ test: /\.(jsx|js)$/, exclude: /node_modules/ , use: 'babel-loader' },
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
};
module.exports = config;
The entry point ./views/Index.js is where I'm importing my css file:
Index.js
import React from 'react';
import Layout from './Layout.jsx';
import PageContent from './PageContent.jsx';
import './global.css';
class Index extends React.Component {
render() {
return (
<Layout title={this.props.title}>
<PageContent />
</Layout>
);
}
}
export default Index;
Inside the imported ./Layout.jsx file I'm using a <link> to include the bundled css file in my page:
Layout.jsx
import React from 'react';
class Layout extends React.Component {
render() {
return (
<html>
<head>
<title>{this.props.title}</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="root">
{this.props.children}
</div>
<script type="text/javascript" src="./bundle.js"></script>
</body>
</html>
);
}
}
export default Layout;
I'm pretty confused because it seems like my app is building fine, but when I try to access my webpage I keep getting a syntax error.
Can anyone please help me understand what I'm doing wrong?
It seems problem with loaders below is example of webpack.config.js file working for jsx and css loaders :
module.exports = {
entry: './app/index.js',
output: {
path: __dirname,
filename: 'dist/bundle.js'
},
devServer: {
inline: true,
port: 3000
},
module: {
loaders: [{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react', 'react-hmre']
}
},
{
test: /\.scss$/,
loaders: [ 'style', 'css', 'sass' ]
}]
}
};
it seems like babel or webpack is not loading the loaders.
This variant helps me with it (just include into webpack.config.js):
require.extensions['.css'] = () => {
return;
};
More here... [link]
Related
I hope you're holding on in these hard times. I'm building a React app but by configuring the webpack first. So, I'm trying to use an image by importing it or referencing it in the image tag but it's not working as it should. May anyone please tell me what I'm doing worng? Thanks in advance.
My webpack file
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './index.js',
output: {
path: path.join(__dirname, '/dist'),
filename: 'index_bundle.js',
publicPath: 'dist'
},
devServer: {
inline: true,
contentBase: './dist',
port: 8080
},
performance: {
hints: 'warning',
maxEntrypointSize: 400000
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{loader: 'babel-loader'},
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(jpg|png|svg)$/,
use:{
loader: 'url-loader',
}
},
{
resolve: {
alias: {
public: path.join(__dirname, '/public')
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
})
]
}
My Navbar file
import { NavbarBrand, Navbar, NavLink } from 'reactstrap';
import logo from '../public/clean_boy';
const imageStyle={
height: "60px",
width: "100%",
padding: "20px 20px -10px 10px",
marginRight: "10px"
}
const NavBar = () => {
return (
<div>
<Navbar dark color="dark">
<NavbarBrand href="/" className="fluid"><img src={logo} style={imageStyle}/>Domestic Workers</NavbarBrand>
<NavLink href="#">Log In</NavLink>
</Navbar>
</div>
)
}
export default NavBar;
Server Error
Module not found: Error: Can't resolve '../public/clean_boy' in '/Users/moise.rwibutso/Andela - Sims Apps/Domestic-workers-system/UI/components'
# ./components/NavBar.js 3:0-39 19:9-13
# ./components/App.js
# ./index.js
ℹ 「wdm」: Failed to compile.
I'm trying to create a server rendered react app, the only part I'm stuck on is importing my components to my express server and getting the static markdown to send back to the user. Essentially what I have right now is this:
Express server:
const Report = require('../public/source/components/index.js').default;
....
router.get('/*', function(req, res, next) {
var reportHTML = ReactDOMServer.renderToStaticMarkup(react.createElement(Report)))
res.render('index', { title: 'Report' });
});
When I hit that route, I get the following error:
Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite components)
but got: object. You likely forgot to export your component from the file
it's defined in. Check the render method of `ReportApp`.
in ReportApp
The contents of my index.js file, note that I stripped out a lot of the complexity involving graphql and setting the initial state, which is why this isn't a functional component.
import React, { Component } from 'react';
import Header from './header/Header';
import PageOneLayout from './pageOneLayout/PageOneLayout';
import styles from './main.scss';
const hexBackground = require('./assets/hex_background.png');
export default class ReportApp extends Component {
render() {
return (
<div className={styles.contentArea}>
<img src={`/build/${hexBackground}`} alt={'hexagonal background'} className={styles.hexBackground}/>
<Header client={"client name"} />
<div className={styles.horizontalLine}></div>
<PageOneLayout chartData={this.state} />
</div>
)
}
}
Any pointers in the right direction would be appreciated!
EDIT:
here's my webpack:
/* eslint-disable no-console */
/* eslint-disable import/no-extraneous-dependencies */
import autoprefixer from 'autoprefixer';
import nodemon from 'nodemon';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
nodemon({
script: './bin/www',
ext: 'js json',
ignore: ['public/'],
});
nodemon.on('start', () => {
console.log('App has started');
}).on('quit', () => {
console.log('App has quit');
}).on('restart', files => console.log('App restarted due to: ', files));
export default {
watch: true,
entry: './public/source/main.js',
output: { path: `${__dirname}/public/build/`, filename: 'main.js' },
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-1'],
plugins: ['transform-decorators-legacy'],
cacheDirectory: true
}
},
// {
// test: /\.jsx?$/,
// exclude: /node_modules/,
// loader: 'eslint',
// },
{
test: /\.s?css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader!sass-loader?outputStyle=expanded&sourceMap')
},
{ test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff$|\.ttf$|\.wav$|\.mp3$/, loader: "file", output: {path: `${__dirname}/public/build/`, filename: 'logo.svg'}},
],
},
// eslint: {
// configFile: './public/.eslintrc',
// },
resolve: {
modulesDirectories: ['node_modules', 'public/source'],
extensions: ['', '.js', '.jsx'],
},
postcss: [
autoprefixer,
],
plugins: [
new ExtractTextPlugin('main.css', { allChunks: true }),
],
};
There are few things to consider:
Are you doing any code transpiling at server side?
How are you building your component bundle(show the config, I assume webpack)?
Make sure the bundle component exposes the component.
The extra createElement shouldn't be needed in this case ReactDOMServer.renderToStaticMarkup(react.createElement(Report))).
I have the following webpack config file:
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/client/public');
var APP_DIR = path.resolve(__dirname, 'src/client/app');
var config = {
entry: [
APP_DIR + '/config/routes.jsx',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080'
],
output: {
publicPath: 'http://localhost:8080/src/client/public/'
},
module : {
loaders : [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: APP_DIR,
exclude: /node_modules/,
query: {
presets: ['es2015']
}
},
{
test: /\.scss$/,
loaders: [ 'style', 'css', 'sass' ]
},
{
test: /\.json$/,
loader: "json-loader"
}
]
}
};
module.exports = config;
all I am trying to do is run my app on localhost, however when I hit: "http://localhost:8080/src/client/home" (as per my routes.jsx and after running webpack-dev-server)
import React from 'react';
import { Route, Router, browserHistory } from 'react-router';
import ReactDOM from 'react-dom';
import Wrapper from './../components/wrapper.jsx';
import Home from './../components/home.jsx';
import Projects from './../components/projects.jsx';
import SingleProject from './../components/projectContent/singleProject.jsx';
import About from './../components/aboutUs.jsx'
ReactDOM.render((
<Router history={browserHistory} >
<Route path="/" component={Wrapper} >
<Route path="home" component={Home} />
<Route path="projects" component={Projects} />
<Route path="projects/:id" component={SingleProject} />
<Route path="about" component={About} />
</Route>
</Router>
), document.getElementById('app'));
I get
"Cannot GET /src/client/home".
First thing you have mentioned in your routes as the home component to have path /home. So you need to visit http://localhost:8080/home. Also if you try to access this url directly, it will give you this error since you are using browserHistory. If you want you can use hashHistory or HashRouter in react-router v4, in which case you will need to visit http://localhost:8080/#/home. If you want to continue using browserHistory or BrowserRouter as in react-router v4, then you will need to add historyApiFallback: true in you webpack
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/client/public');
var APP_DIR = path.resolve(__dirname, 'src/client/app');
var config = {
entry: [
APP_DIR + '/config/routes.jsx',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080'
],
output: {
publicPath: 'http://localhost:8080/src/client/public/'
},
devServer: {
historyApiFallback: true
},
module : {
loaders : [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: APP_DIR,
exclude: /node_modules/,
query: {
presets: ['es2015']
}
},
{
test: /\.scss$/,
loaders: [ 'style', 'css', 'sass' ]
},
{
test: /\.json$/,
loader: "json-loader"
}
]
}
};
module.exports = config;
You need to add this in your webpack settings:
devServer: {
historyApiFallback: true,
},
And start your server like this:
webpack-dev-server --config webpack.config.js
Because you want React-Route to handle the route instead of your server. So no matter what the url is it should goes to index.html.
I have a small trial web application that I'm working on that uses the vue webpack template (https://github.com/vuejs-templates/webpack). I'm pretty new to webpack so I was assuming that I could add in to plugins a new webpack.ProvidePlugin and it would be available globally but when I do a npm run dev I get the following error:
/var/www/public/leadsStatsDashboard/liveleadstats/src/components/Hello.vue
18:17 error 'd3' is not defined no-undef
Which sounds like to me that it can't find the d3 reference. I'm no sure if there's some configuration I skipped over or what but any help would be appreciated. Here is the source for my files
Webpack.dev.conf.js:
var path = require('path')
var config = require('../config')
var utils = require('./utils')
var webpack = require('webpack')
var projectRoot = path.resolve(__dirname, '../')
module.exports = {
plugins: [
new webpack.ProvidePlugin({
d3: 'd3',
crossfilter: 'crossfilter',
dc: 'dc'
})
],
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
publicPath: config.build.assetsPublicPath,
filename: '[name].js'
},
resolve: {
extensions: ['', '.js', '.vue'],
fallback: [path.join(__dirname, '../node_modules')],
alias: {
'src': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../src/assets'),
'components': path.resolve(__dirname, '../src/components'),
'd3': path.resolve(__dirname, '../bower_components/d3/d3.min.js'),
'crossfilter': path.resolve(__dirname, '../bower_components/crossfilter/crossfilter.min.js'),
'dc': path.resolve(__dirname, '../bower_components/dcjs/dc.js')
}
},
resolveLoader: {
fallback: [path.join(__dirname, '../node_modules')]
},
module: {
preLoaders: [
{
test: /\.vue$/,
loader: 'eslint',
include: projectRoot,
exclude: /node_modules/
},
{
test: /\.js$/,
loader: 'eslint',
include: projectRoot,
exclude: /node_modules/
}
],
loaders: [
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.js$/,
loader: 'babel',
include: projectRoot,
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json'
},
{
test: /\.html$/,
loader: 'vue-html'
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url',
query: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url',
query: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
eslint: {
formatter: require('eslint-friendly-formatter')
},
vue: {
loaders: utils.cssLoaders()
}
}
Hello.vue
<template>
<div id="pieChartContainer">
</div>
</template>
<script>
export default {
data () {
return {
// note: changing this line won't causes changes
// with hot-reload because the reloaded component
// preserves its current state and we are modifying
// its initial state.
msg: 'Hello World! This is a test'
}
},
ready () {
console.log(d3.version)
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1 {
color: #42b983;
}
</style>
Your error isn't emitted from webpack, but from eslint.
I think the webpack part works as it should, in fact!
no-undef complains that you are using the global d3 without importing or defining it somewhere.
The good news is, that's easy to fix. Use any of the following three possibilities:
Just add the following block to your .eslintrc.js:
"globals": {
"d3": true
}
...or use eslint comments within the file that requires d3 implicitly (but that doesn't make much sense as you made it available globally and you would need to do this in every file you wish to use the global var):
/* eslint-disable no-undef */
...or you could relax the eslint rule in your .eslintrc.js config:
'rules': {
// all other rules...
'no-undef': 0
}
Additional links:
Direct link to the template's eslintrc file
The eslint 'standard' file the template extends
Further reading on eslint's no-undef rule
Whilst developing using react / webpack / node I reference other components using "import Map from './map.jsx';" or similar statements. I then webpacked to a bundle and attempted to host it on IIS along with an index.html page and the fonts folder. However in the console I get the error: Cannot find module "./map.jsx", as if it's trying to reference a local file, but I thought it was supposed to pack those into the bundle?
If there's anything else I can supply to assist troubleshooting, please let me know.
Here's my map.jsx
import React from 'react';
import 'leaflet';
export default class Map extends React.Component {
componentDidMount() {
this.map = new L.Map('map', {
center: new L.LatLng(53.15, 0.54),
zoom: 8,
layers: L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
})
});
this.layersControl = L.control.layers().addTo(this.map);
}
render() {
return (
<div id="map-container" className="pure-u-1">
<div id="map"></div>
</div>
);
}
}
and my app.jsx
import React from 'react';
import Nav from './nav/nav.jsx';
import NavButton from './nav/navbutton.jsx';
import Map from './map.jsx';
export default class App extends React.Component {
render() {
return (
<div className="pure-g">
<Nav>
<NavButton>Test</NavButton>
</Nav>
<Map />
</div>
);
}
}
as well as the webpack.config.js
module.exports = {
entry: "./src/index.jsx",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
},
{ test: /\.css$/, loader: "style-loader!css-loader" },
{ test: /\.png$/, loader: "url-loader", query: { mimetype: "image/png" } },
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader?limit=10000&mimetype=application/font-woff&name=fonts/[name].[ext]"
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "file-loader?name=fonts/[name].[ext]"
}
]
}
};