Webpack is slick... If only I could get it to work. I have two files.
App.js
App.scss
I want to import the styles from App.scss and use them in App.js
Here is my code.
// App.js
import React, {Component} from 'react';
import s from './App.scss';
class App extends Component {
render() {
return (
<div className={s.app}>
</div>
);
}
}
console.log('what is in s ' + JSON.stringify(s));
export default App;
And Sass file.
// App.scss
.app {
width: 100%;
height: 100%;
background-color: blue;
}
Console shows that s is an empty object. I would expect to see {app: ...}.
Weback is setup like this.
// webpack.config.js
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'source-map',
entry: [
'./src/client',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
module: {
loaders: [
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.js$/,
loader: 'babel-loader',
include: path.join(__dirname, 'src')
}]
},
devServer: {
contentBase: './dist',
hot: true
}
};
No errors from webpack. No errors in the console.
After much searching I found this Github issue. Solution is to change this line in webpack.config.js
loaders: ['style', 'css', 'sass']
to
loader: 'style!css?modules!sass'
Related
I'm creating a Todo app and I am using webpack to bundle multiple js files. I'm having trouble importing my functions and classes between the different js files. I keep receiving the error "SyntaxError: cannot use import statement outside a module.". I have set the entry in the webpack.config.js file to the index.js file. I can import from all the other js files into the index.js file and it works. Where I am having trouble is importing between all the js files themselves. I am fairly new to webpack and any help would be greatly appreciated. Thanks!
This is the task.js file code that I am trying to import into the ui.js file.
import { v4 as uuidv4 } from 'uuid';
export class Task {
constructor(title, description, dueDate) {
return Object.assign(this, { id: uuidv4(), title, description, dueDate, completed: false })
}
}
Here is the code in the ui.js file
import { Task } from './task.js';
const taskOne = new Task('Hello', "goodbye")
console.log(taskOne);
Here is the webpack.config.js file
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
assetModuleFilename: '[name][ext]'
},
devtool: 'source-map',
devServer: {
static: {
directory: path.resolve(__dirname, 'dist')
},
port: 3000,
open: true,
hot: true,
compress: true,
historyApiFallback: true
},
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.(png|jpg|jpeg|svg|gif)$/i,
type: 'asset/resource'
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Todo App',
filename: 'index.html',
template: './src/template.html'
})
]
}
This is my source code ./source/client/main.jsx.
export default {
test: () => console.log('Flow')
};
And this is my webpack.config.cjs.
const path = require('path');
const webpack = require('webpack');
const packageJSON = require('./package.json');
module.exports = (env, argv) => {
return {
mode: 'development',
entry: './source/client/main.jsx',
// entry: './main.js',
output: {
path: path.join(__dirname, 'release'),
filename: 'main.js',
library: {
name: packageJSON.name,
type: 'umd'
}
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'#babel/preset-env',
'#babel/preset-react'
],
plugins: [
'#babel/plugin-transform-runtime'
]
}
}
}
]
}
};
};
My package.json contains a list of dependencies and both main and module pointing to the webpack product.
"main": "./release/main.js",
"module": "./release/main.js",
However, when I try to import my module in another webpack project, I get the default was not found error.
import Test from 'test';
export 'default' (imported as 'Test') was not found in 'test' (module has no exports)
Am I building the module wrong?
I'm starting an Angular project and have been following these steps to import the scss files - https://github.com/AngularClass/angular-starter/wiki/How-to-include-SCSS-in-components
So looking at src/scss my style.scss is present
webpack.common.js has a sass loader module defined - sassLoader: {
includePaths: [path.resolve(__dirname, '..', 'src/scss')],
sourceMap: true
},
I've also looked at a similar question on SO posted here which doesn't explain how to import the style globally:
How do you include .scss file to a component in angular2?
But in comparison with the example linked above my app.js file is configured like so:
import angular from 'angular';
import uiRouter from 'angular-ui-router';
import Components from './components/components';
import { HomeComponent } from './home/home.component';
import {
CheapFlightService,
AirportsService
} from './services';
angular.module('myApp', [
uiRouter,
Components
])
.component('homePage', HomeComponent)
.service('AiportsService', AirportsService)
.service('CheapFlightService', CheapFlightService)
.config(($stateProvider) => {
'ngInject';
$stateProvider
.state('home', {
url: '',
template: '<home-page></home-page>'
});
});
Question:
How can you import .scss file to app.js parent file as a global?
style.scss file:
//----------------------------------*\
// SCSS MIXINS
//----------------------------------*/
#import 'mixins/_position.scss';
#import 'mixins/_selection.scss';
#import 'mixins/_vendor.scss';
#import 'mixins/_other-mixins.scss';
//----------------------------------*\
// CONFIG MODULES
//----------------------------------*/
// Config modules
#import 'modules/_vars.scss';
#import 'modules/_clearfix.scss';
#import 'modules/_defaults.scss';
//----------------------------------*\
// PARTIALS
//----------------------------------*/
#import 'partials/_header.scss';
#import 'partials/_nav.scss';
#import 'partials/_sidebar.scss';
#import 'partials/_main.scss';
#import 'partials/_footer.scss';
//----------------------------------*\
// OBJECTS & MODULES
//----------------------------------*/
#import 'modules/_buttons.scss';
#import 'modules/_inputs.scss';
#import 'modules/_lists.scss';
#import 'modules/_typography.scss';
#import 'modules/_misc.scss';
#import 'modules/_app.scss';
// Enhancement modules
#import 'modules/_breakpoints.scss';
#import 'modules/_print.scss';
webpack.common.js:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CommonsChunkPlugin = require('webpack-vendor-chunk-plugin');
const autoprefixer = require('autoprefixer');
module.exports = {
entry: {
app: './src/app.js'
},
output: {
path: path.join(__dirname, '..', 'dist'),
filename: '[name].js'
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html',
inject: 'body'
}),
],
module: {
loaders: [
{ test: /\.js$/, loaders: ['ng-annotate','babel-loader'], exclude: /node_modules/ },
{ test: /\.html$/, loader: 'raw' },
// inline base64 URLs for <=8k images, direct URLs for the rest
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'},
// helps to load bootstrap's css.
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&minetype=application/font-woff' },
{ test: /\.woff2$/,
loader: 'url?limit=10000&minetype=application/font-woff' },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&minetype=application/octet-stream' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file' },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&minetype=image/svg+xml' }
]
},
devtool: 'source-map',
resolve: {
// add alias for application code directory
// alias: {
// '~': path.resolve(__dirname, '..', 'src')
// },
},
sassLoader: {
includePaths: [path.resolve(__dirname, '..', 'src/scss')],
sourceMap: true
},
postcss: function() {
return [autoprefixer];
}
};
Firstly, sassLoader and postcss are not valid webpack config attributes https://webpack.js.org/configuration
The way you would typically go about it is to add the .scss file to your entry
entry: {
app: './src/app.js',
styles: './pathtoyourstyles/style.scss'
},
and then add the appropriate loaders.
loaders: [
{
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
}
]
I'm newbie in webpack and react. hope you can help me.
I faced a problem and can't find any working solution in the internet.
When i trying to run webpack-dev-serverI geting "Module not found: Error: Cannot resolve module 'components/app'" error all the time.
Here my files structure.
root/ webpack.config.js
var webpack = require('webpack');
var path = require('path');
module.exports = {
devtool: 'inline-source-map',
entry: [
'webpack-dev-server/client?http://127.0.0.1:8080/',
'webpack/hot/only-dev-server',
'./src'
],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
resolve: {
moduleDirectories: ['node_modules', 'src'],
extensions: ['', '.js']
},
module: {
loaders: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
};
root/ .babelrc
{
presets: ["react", "es2015"],
plugins: ["react-hot-loader/babel"]
}
root/src/index.js
import React from 'react';
import { render } from 'react-dom';
import App from 'components/app';
render(<App />, document.getElementById('app'));
root/src/components/app.js
import React from 'react';
export default class App extends React.component {
render() {
return (
<div>
<h1>Hello There</h1>
</div>
);
}
}
I agree with Robert Moskal answer, use Relative path to import, at the same time if you really want the absolute path to work you may have to add one more line in your webpack.config.js inside your resolve section of it add this below line
root: path.resolve('./src'),
this will help to resolve the root and you can easily import using absolute path from folders inside the src folder. I would show you my sample webpack.config.js below
'use strict';
const path = require('path');
const loaders = require('./webpack/loaders');
const plugins = require('./webpack/plugins');
const applicationEntries = process.env.NODE_ENV === 'development'
? ['webpack-hot-middleware/client?reload=true']
: [];
const mainEntry = process.env.NODE_ENV === 'development'
? './src/sample/index.tsx'
: './src/lib/index.tsx';
module.exports = {
entry: [mainEntry].concat(applicationEntries),
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js',
publicPath: '/',
sourceMapFilename: '[name].js.map',
chunkFilename: '[id].chunk.js',
},
devtool: process.env.NODE_ENV === 'production' ?
'source-map' :
'inline-source-map',
resolve: {
root: path.resolve('./src'),
extensions: [
'',
'.webpack.js',
'.web.js',
'.tsx',
'.ts',
'.js',
'.json',
],
},
plugins: plugins,
devServer: {
historyApiFallback: { index: '/' },
},
module: {
preLoaders: [
loaders.tslint,
],
loaders: [
loaders.tsx,
loaders.html,
loaders.css,
loaders.scss,
loaders.eot,
loaders.svg,
loaders.ttf,
loaders.woff,
loaders.json,
{
test: /\.png$/,
loader: 'url-loader',
query: { mimetype: 'image/png' },
},
],
},
externals: {
'react/lib/ReactContext': 'window',
'react/lib/ExecutionEnvironment': true,
'react/addons': true,
},
};
You need to specify a relative path to app in your index.js file. So
import App from './components/app'
Without the relative path notation, the module import system looks in the node_modules directory.
You're looking for module aliasing. The resolve section of your config should look something like:
const path = require('path');
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
extensions: ['', '.js'],
alias: {
components: path.resolve(__dirname, 'src/components/')
}
}
This is equivalent to the paths option in TypeScript config files.
I'm using babel loader with webpack for combining multiple React components. Although I've installed webpack and babel-loader along with its dependencies. I'm getting two errors:
ERROR in ./components/layout.jsx
Module parse failed: /Users/myuser/Desktop/Projects/Demo/Scorecard/SPA/React/components/layout.jsx Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| import React from 'react';
|
| class Layout extends React.Component {
# ./build/import.js 15:14-49
ERROR in ./components/topic-list.jsx
Module parse failed: /Users/myuser/Desktop/Projects/Demo/Scorecard/SPA/React/components/topic-list.jsx Line 17: Unexpected token <
You may need an appropriate loader to handle this file type.
| render: function () {
| return (
| <div>
| <div className="row topic-list">
| <SingleTopicBox
# ./build/import.js 11:17-56
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'build');
var APP_DIR = path.resolve(__dirname, 'build');
module.exports = {
entry: APP_DIR + '/import.js',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: APP_DIR,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['es2015']
}
}
],
resolve: {
extensions: ['', '.js', '.jsx']
}
}
};
import.js
import React from 'react';
import ReactDOM from 'react-dom';
import TopicsList from '../components/topic-list.jsx';
import Layout from '../components/layout.jsx';
layout.jsx
import React from 'react';
class Layout extends React.Component {
render() {
return (
<div className="container">
<TopicsList />
</div>
);
}
};
ReactDOM.render(<Layout />, document.getElementById('app'));
Remove include options from your webpack.config.js file. Include folder should be the folder where webpack can find your loader in this case babel loader
I'm not clear about your file structure but it might be the include part in resolve section of your webpack.config.js that results the problem.
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'build');
var APP_DIR = path.resolve(__dirname, 'build');
module.exports = {
entry: APP_DIR + '/import.js',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: THIS_SHOULD_BE_YOUR_SOURCE_FOLDER,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['es2015']
}
}
],
resolve: {
extensions: ['', '.js', '.jsx']
}
}
};
You seem to be missing the React preset for Babel: babel-preset-react
npm install --save-dev babel-preset-react
And add it to your babel-loader presets.
I had the same case and resolved it by removing the exclude part of the webpack rule (since the failing import was an import of an imported npm package that was in the node_modules directory).
So, applying to your example:
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'build');
var APP_DIR = path.resolve(__dirname, 'build');
module.exports = {
entry: APP_DIR + '/import.js',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: APP_DIR,
loader: 'babel',
// we want the loader to search in node_modules,
// so we comment the line below
// exclude: /node_modules/,
query: {
presets: ['es2015']
}
}
],
resolve: {
extensions: ['', '.js', '.jsx']
}
}
};