I added SASS to my project because I like using SASS for my CSS. In my app folder I made CSS folder and a SCSS folder. I run sass --watch scss:css to map over my scss changes to the css folder. This is working great, I think. In my webpack I added a loader to handle SCSS and SASS and added the files need to my package.json. In order to start using the SASS styles do I need to include them in my index.html file or do I need to import them into each component I want to use them with the new es6 import x from 'xpath' thing?
Here are my package.json and webpack.config.js files
{
"name": "newaccount",
"version": "1.0.0",
"description": "a form submission for new accounts",
"main": "App.js",
"scripts": {
"start": "webpack-dev-server"
},
"author": "---",
"license": "ISC",
"dependencies": {
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-hot-loader": "^1.3.1",
"react-router": "^3.0.0"
},
"devDependencies": {
"babel-core": "^6.18.2",
"babel-loader": "^6.2.8",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"css-loader": "^0.26.1",
"html-webpack-plugin": "^2.24.1",
"node-sass": "^3.13.0",
"sass": "^0.5.0",
"sass-loader": "^4.0.2",
"style-loader": "^0.13.1",
"webpack": "^1.13.3",
"webpack-dev-server": "^1.16.2"
}
}
webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');
var HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
template: __dirname + '/app/index.html',
filename: 'index.html',
inject: 'body'
});
module.exports = {
entry: [
'./app/App.js'
],
output: {
path: __dirname + '/public',
filename: "index_bundle.js"
},
plugins: [HTMLWebpackPluginConfig],
devServer: {
inline:true,
contentBase: './public',
port: 3333
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}, {
test: /\.scss$/,
include: path.join(__dirname, "app"),
loaders: ["style", "css", "sass"]
},
{
test: /\.scss$/,
loader: 'style!css!sass'
}]
}
};
My file structure is basically an app folder and a public folder. Inside app you have components / containers / css / scss / utils and inside public is jus the bundle.js and index.html files.
You should not be using an external Sass command with Webpack. You need to put the Sass content in Webpack's dependency graph. To do this, tell Webpack you are using the files, which is done with require(). At the top of your Javascript file for the page needing the style, add
require('./path/to/sass/scss')
In development mode, this will turn your Sass code into Javascript that will inject the built CSS rules into the page. It's strange I know, but it gives you hot reloading of styles. You should also have a separate production build Webpack config using the ExtractTextPlugin to pull the built CSS out into a separate file, and load that file in your production HTML.
Further reading: Webpack: When to Use and Why.
My webpack.config.js file was loading scss and sass twice, changed it to
{
test: /\.scss$/,
loader: 'style!css!sass'
}]
by removing
{
test: /\.scss$/,
include: path.join(__dirname, "app"),
loaders: ["style", "css", "sass"]
},
Now I can include my SASS files in my react components. Now I need to figure out how to access my images inside of my SASS files - seems to toss mass errors =(
Related
I've been fighting with webpack and loosing for the last day and a half and I give up, please help!
So what I'm trying to do is create an NPM package that will be used in many of our sites. We have multiple sites with a shared functionality, we are using redux and I have made an npm package that provides actions, reducers and middleware that can be imported across multiple projets. That works great, no worries there. I am now trying to make a second package that contains components that use the main application's state from the redux store.
This second package uses selectors and dispatches actions provided by the first package.
I wrote the component in the main application, works great,
I created a new project for the second package, copy and pasted the component, it's scss module file, added the first package and other dependancies as peer dependancies
built with webpack (after some troubles with peer dependancies not being found, I had to install them with install-peers, maybe this has something to do with my problem)
I then npm installed the package in the main application... and I'm getting "store is undefined".
I think there is a problem with my webpack config, somehow the component doesn't seem to have access to my application's store as if it exists in its own little world. This is my guess, I could be miles off.
We are using react, next, redux and scss modules.
Here is my webpack config (externals are commented out as I'm using peer-deps-externals-webpack-plugin):
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
var path = require("path");
var PeerDepsExternalsPlugin = require('peer-deps-externals-webpack-plugin');
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve("build"),
filename: "index.js",
// libraryTarget: "commonjs2",
library: 'mm-chat-components',
libraryTarget: 'umd',
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles.css',
chunkFilename: 'styles.css'
}),
new PeerDepsExternalsPlugin()
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.module\.s(a|c)ss$/,
loader: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
},
{
test: /\.s(a|c)ss$/,
exclude: /\.module.(s(a|c)ss)$/,
loader: [
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
]
},
externals: {
// react: "react",
// reactDOM: 'react-dom',
// mmTheme: 'mm-theme',
// mmChatRedux: 'mm-chat-redux',
// mmReduxBase: 'mm-redux-base',
// redux: 'redux',
// reactRedux: 'react-redux',
// finalForm: 'final-form',
// reactFinalForm: 'react-final-form',
// twilioChat: 'twilio-chat'
}
};
Here is my package.json:
{
"name": "mm-chat-components",
"version": "1.0.0",
"description": "",
"main": "./build/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build-webpack": "webpack --mode production"
},
"author": "",
"license": "ISC",
"peerDependencies": {
"mm-redux-base": "git+https://github.com/MMTSURVEY/mm-redux-base.git",
"mm-theme": "git+https://github.com/MMTSURVEY/mmj-theme.git",
"final-form": "^4.18.7",
"react-final-form": "^6.3.5",
"react": "^16.13.1",
"twilio-chat": "^3.3.7",
"react-redux": "^7.2.0",
"react-dom": "^16.12.0",
"mm-chat-redux": "git+https://github.com/MMTSURVEY/mm-chat-redux.git"
},
"devDependencies": {
"#babel/cli": "^7.0.0",
"#babel/core": "^7.0.0",
"#babel/preset-env": "^7.0.0",
"#babel/preset-react": "^7.9.4",
"babel-loader": "^8.1.0",
"babel-plugin-react-css-modules": "^5.2.6",
"babel-plugin-react-css-modules-sass": "^1.1.0",
"css-loader": "^3.5.3",
"install-peers": "^1.0.3",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.14.1",
"peer-deps-externals-webpack-plugin": "^1.0.4",
"sass-loader": "^8.0.2",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0"
}
}
And my babelrc:
{
"presets": ["#babel/preset-env", "#babel/preset-react"]
}
I'm generally lost when using webpack, it still seems like magic that's far beyond my comprehension.
That's lots of info, I hope it's all clear! Thanks in advance for any help! You guys rock.
Beau
I am attempting to use this cool React Button Component inside my project but I do not understand where I am going wrong and how my Webpack isn't working. Please could you help! I am also new at Webpack and I would appreciate it if you could point me in the right direction. Much Thanks :)
I get this error message:
[ error ] ./node_modules/react-awesome-button/src/styles/styles.scss 2:0
Module parse failed: Unexpected character '#' (2:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| // [Default] Variables
> #import './base/variables.scss';
| // [Default] Custom Properties
| #import './base/custom-properties.scss';
Package.json
{
"name": "test",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "9.0.8",
"react": "16.10.2",
"react-awesome-button": "^6.1.2",
"react-dom": "16.10.2",
"styled-components": "^4.4.0"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^8.0.6",
"babel-preset-cgb": "^1.7.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"file-loader": "^4.2.0",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.12.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"webpack": "4.36.0",
"webpack-cli": "^3.3.9"
}
}
Webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
module.exports = {
entry: './pages/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
},
{
test: /\.ts$/,
use: 'ts-loader'
},
{
test: /\.css$/,
use: [
// style-loader
{ loader: 'style-loader' },
// css-loader
{
loader: 'css-loader',
options: {
modules: true
}
},
// sass-loader
{ loader: 'sass-loader' }
]
},
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
]
},
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' })
],
mode: 'production'
};
Breaks on this line:
import AwesomeButtonStyles from "react-awesome-button/src/styles/styles.scss";
The styles file that you're importing to your HTML, is it a .css extension or .scss extension? If you're just using .scss files then you need to change your test Regex in your webpack folder to look for that extension.
test: /\.scss$/
If however you're using files with both extension types, then you'll want to use a test value like below. The question mark looks for 0 or more occurrences of the s, so it will work for scss and css files.
test: /\.s?css$/
Let me know if that helps at all.
I have a monorepo set up with a file structure like:
/root
/-ProjectA
/-ProjectB
/-common
In /ProjectA, I have a React app which imports a file from /common. When I try to start it in the Webpack Dev Server, I get an error from Babel-Loader saying that there is a compilation error in the imported common file where the JSX starts.
If I move the common file into ProjectA and import from there, everything works fine so there is no problem in that specific file (plus it's a very simple contrived example at this point).
/common/index.js (this is the only files in this directory)
import React from 'react';
export default () => <span>Hello, World!</span>;
/ProjectA/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Hello from '../common';
const App = () => <div><Hello /></div>;
ReactDOM.render(<App />, document.querySelector('#root'));
/ProjectA/.babelrc
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
]
}
/ProjectA/webpack.config.js
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
include: [
path.resolve('.'),
path.resolve('../common'),
],
use: {
loader: 'babel-loader'
}
}
/ProjectA/package.json
{
"dependencies": {
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"#babel/core": "^7.5.4",
"#babel/preset-env": "^7.5.4",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.6",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.35.3",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.7.2"
}
}
Why is babel unable to transpile files from outside the current directory? Is there a way around this or a problem in my configs maybe?
Add this line to webpack.config.js
devServer: { contentBase: path.join(__dirname, "public") }
add this script to package.json
"scripts":{
"dev-server": "webpack-dev-server",
}
config.webpack.js(without styling loaders)
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
module: {
rules: [{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
},
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: path.join(__dirname, 'public')
}
};
now this command should run your app.
npm run dev-server
I'm pretty new to using React with webpack; is this a reasonable config file? What would you add or subtract?
const path = require('path');
const webpackConfig = {
entry: path.resolve(__dirname, 'ENTRY'),
output: {
path: path.resolve(__dirname, 'STATIC'),
filename: 'bundle.js',
},
module: {
loaders: [],
},
resolve: {
extensions: ['.js', '.jsx'],
},
devtool: 'inline-source-map',
};
webpackConfig.module.loaders.push({
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: { presets: ['es2015', 'react']},
});
webpackConfig.module.loaders.push({
test: /\.(scss|css)$/,
loaders: ['style-loader', 'css-loader', 'sass-loader'],
});
module.exports = webpackConfig;
Also, I'm not entirely sure what dependencies are needed to make this work. There are a few different babel dependencies that have been preloaded into my project folder, but I only see a couple being referenced here (namely, the babel-loader and es2015/react presets).
In my package.json I have
"devDependencies": {
"babel": "^6.23.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-latest": "^6.24.1",
"babel-preset-react": "^6.24.1",
"webpack": "^3.6.0"
},
What you use in your webpack and package.json files is dependent on the needs of your app. For example, if your app handles a lot of images you might want to consider adding a loader that could handle images, such as url-loader. If you want it to handle more dynamic css classes, you might want to add the classNames npm module. So what you have right now works... but it's hard to say what to add without knowing what you're building.
In my personal opinion, I suggest you use create-react-app since you are still new. This way you don't have to deal with configuring your webpack and can focus on the fundamentals of react.
So let me start my saying I am fairly new to WebPack and React, but I have something basic working (at least it works in the browser). I am however an ok C# developer, so want to use Visual Studio as my editor of choice. I have created a fairly simple webpack setup and created a dummy solution file (Visual Studio 2015 update 3), where I have created a web site from file system.
I have a working (in the browser) Webpack + TypeScript + React + Babel setup which as I say works famously in the browser. It is largely based on the official guidelines for using TypeScript with React https://www.typescriptlang.org/docs/handbook/react-&-webpack.html
I have followed that tutorial to the letter and even though it runs in the browser just fine also suffers from the same issue as my richer webpack setup.
So what is the issue exactly?
The main issue is that my setup doesn't seem to recognise "React" as a valid module import inside of a TSX file (even though everything is fine in the browser).
I have have read so many posts that talk about different Webpack settings, and tsconfig.json settings that my head is spinning.
I thought it might be better to show you some of my files to see if anyone knows how to fix my issue
.babelrc
{ "presets": ["es2015"] }
package.json (I am using NPM)
{
"name": "task1webpackconfig",
"version": "1.0.0",
"description": "webpack 2 + TypeScript 2 + Babel example",
"repository": {
"type": "git",
"url": "git+https://github.com/sachabarber/MadCapIdea.git"
},
"keywords": [
"babel",
"typescript",
"webpack",
"bundling",
"javascript",
"npm"
],
"author": "sacha barber",
"homepage": "https://github.com/sachabarber/MadCapIdea#readme",
"dependencies": {
"#types/react": "^15.0.23",
"#types/react-dom": "^15.5.0",
"lodash": "^4.17.4",
"react": "^15.5.4",
"react-dom": "^15.5.4"
},
"devDependencies": {
"#types/lodash": "^4.14.63",
"#types/react": "^15.0.23",
"#types/react-dom": "^15.5.0",
"awesome-typescript-loader": "^3.1.3",
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-es2015-native-modules": "^6.9.4",
"source-map-loader": "^0.2.1",
"typescript": "^2.3.2",
"webpack": "^2.4.1"
}
}
tsconfig.json
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"moduleResolution": "Node",
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react"
},
"include": [
"./src/**/*"
]
}
webpack.config.js
let _ = require('lodash');
let webpack = require('webpack');
let path = require('path');
let babelOptions = {
"presets": ["es2015"]
};
function isVendor(module) {
return module.context && module.context.indexOf('node_modules') !== -1;
}
let entries = {
index: './index.tsx'
};
module.exports = {
context: __dirname + '/src',
entry: entries,
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
devServer: {
open: true, // to open the local server in browser
contentBase: __dirname,
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
extensions: [".tsx", ".ts", ".js", ".jsx"],
modules: [path.resolve(__dirname, "src"), "node_modules"]
//modulesDirectories: ['src', 'node_modules'],
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor'],
minChunks: function (module, count) {
// creates a common vendor js file for libraries in node_modules
return isVendor(module);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
chunks: _.keys(entries),
minChunks: function (module, count) {
// creates a common vendor js file for libraries in node_modules
return !isVendor(module) && count > 1;
}
})
],
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader' 1st
// then 'babel-loader'
// NOTE : loaders run right to left (think of them as a cmd line pipe)
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
},
{
loader: 'awesome-typescript-loader'
}
]
},
// All files with a '.js' extension will be handled by 'babel-loader'.
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
}
]
},
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
}
]
}
};
When I run webpack all seems fine
Some of you may be wondering about my project structure which looks like this
And let me just show you that the typings for React/ReactDom are also present
Like I say when I run this, all seems ok, I get what I expect
A working react web page
A set of bundle files (which Index.html uses)
A Source map for my code
So this tells me the React module can be loaded by webpack/browser are working ok.
But when I try and edit the TSX (typescript JSX files) I see this
Typescript is 100% working for my own files, just cant seem to see React stuff.
Like I say I have tried so many suggested fixes and none have worked, please help me someone