Compile .jsx files instead of .js using babel - reactjs

I'm starting to learn ReactJs, and I was trying to build an environment from scratch using this "builder".
Everything works pretty well, but I'd like to work with .jsx files instead of .js (the text editor screws up otherwise, and ir feels better using a different extension for not-compiled scripts)
However, I didn't manage to compile such .jsx files, it only works with .js files.
This is the configuration files for .babelrc:
{
"presets":["es2015","react"]
}
And my webpack.config.js:
var path = require('path');
var config = {
context: path.join(__dirname,'src'),
entry:[
'./main.js'
],
output:{
path :path.join(__dirname,'www'),
filename:'bundle.js'
},
module:{
loaders:[
{
test: /\.js$/,
exclude:/node_modules/,
loaders:['babel']
}
],
},
resolveLoader:{
root: [
path.join(__dirname,'node_modules')
]
},
resolve:{
root:[
path.join(__dirname,'node_modules')
]
}
};
module.exports = config;
I tried simply changing the extensions in the webpack config file from js to jsx, but to no avail.
Any ideas?

Just replace this line:
test: /\.js$/,
with:
test: /\.jsx$/,
It will run babel loader on the .jsx files, instead of .js files.
If you want to transpile both .js and .jsx, you can set it to /\.jsx?$/, where ? in regex indicates to match 0 or 1 occurrences of the preceding character: test positive for both .js and .jsx.
.test property indicates a condition that must be met to run the loader specified in the loader key. You can read more about module.loader options here.
Also, when importing modules, you should add the .jsx extension, like this:
import Counter from './Counter.jsx';
Or set webpack's resolve.extensions config to add .jsx extension (by default, it looks only for .js files). Like this:
resolve: {
/* ... */
extensions: ['', '.js', '.jsx']
}
This way, you can import your files without the extension:
import Counter from './Counter';

Related

Why CSS loader of webpack not working?

I am making the toy example described in the documentation of css-loader:
https://github.com/webpack-contrib/css-loader
I also tried this basic guide that suggest the same: https://css-tricks.com/css-modules-part-2-getting-started/
However, both VS Code highlight and when bundling through the command line complain that the module of the CSS file is not available. Like it does not really recognize it. I have checked I indeed really have installed css-loader, webpack etc. Other than the css loader, webpack is working fine for javascript, typescript etc. So it is really just a problem with CSS. Any ideas why failing?
The error I get is:
TS2307: Cannot find module 'styles.css'.
My file:
import test from 'styles.css';
I tried also without file extension, with and without curly braces etc. But really followed the toy example in the docu of css-loader.
My webpack.config file:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const config = {
entry: "./src/index.tsx",
resolve: {
extensions: ['.tsx', '.js', '.css']
},
output: {
filename: "bundle.js",
},
plugins: [
new HtmlWebpackPlugin({
title: 'title Cool!',
}),
],
module: {
rules: [
{
test: /.tsx$/,
loader: "ts-loader" ,
},
{
test: /.css$/,
use: [ 'style-loader', 'css-loader' ],
}
]
}
}
module.exports = config;
Any ideas?
Are you sure you need a named import? This should work: import './styles.css';.
The problem was related to typescript and not to webpack or the css loader.
So I needed to add css files to modules for typescript:
declare module '*.css' {
const content: any;
export default content;
}
Did the trick. No clue why this is not mention in any of the dozens of tutorial and guides I saw.
You should provide a relative path to your file:
import test from './path/to/styles.css';

Webpack 4 as JSX files

Is there a way to load JSX files on Webpack 4?
I tried:
module.exports = {
resolve: {
extensions: [".jsx", ".js"]
}
}
But apparently my src/index.jsx file is loaded but not processed.
What you have here is half of it. resolve.extensions lets you
require('./my-module.jsx')
without having to type in the .jsx portion. ie
require('./my-module')
However, as you noted - the source is not processed in any way so if you have syntax that needs to be transpiled such as jsx, you'll need to take care of that.
Webpack by default won't do this for you, you'll need to use babel-loader with a preset or plugin that will transform the syntax. There's a lot of tutorials how to do that but it would look something like this:
module: {
rules: [{
exclude: /node_modules/, // don't transpile node_modules
test: /\.jsx$/, // do transpile any files ending in .jsx
use: {
loader: 'babel-loader',
options: {
plugins: ['#babel/plugin-transform-react-jsx']
}
}
}]
}
you need to install
npm i #babel/preset-react --save
add this to .babelrc file inside presets array. We use loaders inside module property of the webpack.config object because loaders are effective on one type of files whereas plugins are effective on the entire bundle.
.babelrc
{
"presets": [
["#babel/preset-env", { "targets": { "esmodules": true } }],
"#babel/preset-react"
],
all webpack projects needs #babel/preset-env. you might install that as well.
}

webpack css loader exclude css files

Currently, I have multiple css files under some react components. Those css files are required conditionally. However, css loader and extract text plugin include all the css files which is not required in a js file. Is there any way to exclude files by regex using test config or other way?
test: /\.css$/,
lets say I have css files
bear.css
cat.css
styles.css
colors.css
... multiptle different css files
I edit the regex correctly but still it include all css no matter what which i tested by leaving one comment on css file which should not be included on bundle.css
This is how I require css file
const css = require(`./styles/${config}`)
I will answer myself. Webpack's include exclude used to determine the file need to be transpile or not, which is nothing to do with excluding files from your bundle. For example, you add regex to exclude, it will still be in your bundle. However, it will not be processed or transpiled(depends on your loader you use).
Therefore, you should use something likeignore loader to remove from your bundle.
According to webpack documentation you can include style-loader and css-loader in your webpack.config.js file:
config = {
entry: "./app/Main.js",
output: {
publicPath: "/",
path: path.resolve(__dirname, "app"),
filename: "bundled.js"
},
mode: "development",
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-react", ["#babel/preset-env", { targets: { node: "12" } }]]
}
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
]
}
}
After that you could add css directly in your Main.js file
import Example from 'Example';
import './css/bear.css';
import './css/cat.css';
...

How to build unified $templateCache when migrating AngularJS 1.x project from gulp & bower to webpack 3

Have a large AngularJS 1.6 project (~120 JS files), which is currently built through gulp/bower.
Looking to migrate over to using yarn & webpack, and we would prefer not to have to modify our project files just to implement webpack. Each of our AngularJS component JS files are wrapped in a IIFE, so they are already out of the global scope.
One of our gulp steps uses the gulp-angular-templatecache module, which collects all of our HTML files and neatly compacts them into a single $tmplateCache loader module.
angular.module("ourApp").run(["$templateCache", function ($templateCache) {
$templateCache.put("/app/components/ourComponent1.html", "<div id=\"component1-html\"> ... </div>\r\n");
$templateCache.put("/app/components/ourComponent2.html", "<div id=\"component2-html\"> ... </div>\r\n");
// etc...
});
I have managed to figure out how to resolve most of our other build processes using webpack, but this one is giving me a problem.
I have looked at the ngtemplate-loader package, but do not think this would work for our needs because of the following:
Would require us to update all of our existing HTML templates to use 'require("./template.html")'
This would create a separate webpack module for each HTML template, which seems very inefficient.
Probably most important, I haven't been able to get it to work.
The current webpack configuration I have setup is based on a simple demo, and splits the project files out from the vendor files. Our project files are bundled up into a 'app.[hashcode].js' file into the /dist folder.
Ultimately, I would like to be able to inject the compiled $templateCache module, into a specific point in our final 'app.[hashcode].js' bundle file. However, right now I would be satisfied with the $templateCache definition file being created into a separate bundle file.
Is there an existing webpack plugin, or loader, or combination of plugin(s)/loader(s), that I could use to accomplish this build step? Is this even possible with webpack?
This is the base directory structure for the demo project:
/dashboard
/app
/assets
/global
global.less
app.less
/components
/controllers
dashboard.controller.js
/directives
yep-nope.directive.js
/messenger
messenger.directive.js
messenger.html
/services
github-status.service.js
dashbboard.config.js
dashboard.module.js
app.js
/dist
app.4f12bb49f144e559bd9b.js
assets.css
index.html
vendor.b0a30c79aa77e0126a5c.js
index.html
package.json
webpack.config.js
This is the current working webpack.config.js file:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
context: __dirname,
entry: {
app: path.resolve(__dirname, 'app/app.js'),
vendor: ['angular','angular-sanitize']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'less-loader']
})
},
{
test: /\.js$/,
loader: 'ng-annotate-loader'
},
{
test: /\.html$/,
exclude: path.resolve(__dirname, 'app/index.html'),
use: [
{ loader: 'html-loader', options: { minimize: false } }
]
}]
},
plugins: [
new CleanWebpackPlugin(['dist','assets/**/*.css']),
new HtmlWebpackPlugin({
title: 'GitUp',
template: 'index.html',
inject: 'body'
}),
new webpack.optimize.CommonsChunkPlugin({
name:"vendor", filename:"[name].[chunkhash].js"
}),
new ExtractTextPlugin('assets.css')
]
};
This is the webpack 'entry' file app/app.js:
require('./assets/app.less');
require('../node_modules/angular/angular.js');
require('../node_modules/angular-sanitize/angular-sanitize.js');
require('./components/dashboard.module.js'); // Define module
require('./components/dashboard.config.js'); // Setup config
// Load in all components files, except for files already loaded above
var reqCtx = require.context('./components', true, /^(?!.*(?:dashboard\.config|dashboard\.module)).*\.js$/);
reqCtx.keys().forEach(reqCtx);
If needed, I can provide the entire sample project...
This may or may not be the answer you're looking for but in the past I've used html-loader to allow me to require my component template URLs, and it worked brilliantly:
https://www.npmjs.com/package/html-loader
It just inlines the template in your bundled script.

React Webpack initial build and runtime

I'm new to React and I'm still trying to understand how things are put together. In webpack, I understand that we have to run the webpack command initially and it will generate the index.js file where we output it in the config. For my questions:
What role does this file play in runtime?
Everytime i do an npm start, does it automatically update my index.js file?
Here is my webpack.config:
var config = {
entry: './main.js',
output: {
path: __dirname,
filename: 'index.js',
},
devServer: {
inline: true,
port: 8080
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
}
]
}
}
module.exports = config;
With or without initially running webpack command my code still runs, reason for me being confused as to what it really does, because even without having the index.js in my directory I'm still able to run my code
Why we are using webpack:
When we run webpack command it will create a single index.js file in given the location.Our browser understands only vanilla html, css and javascript.But with react you are probably going to use jsx or es6. So we need to transform these to what browser understands.
According to your webpack.config , webpack is going to convert all jsx file into .js file (using bable loader)and bundle it to a single file as index.js.
Role plays by index.js:
You will be having an index.html file in your app directory.webpack automatically load index.js file to body of index.html file.This if final index.js file browser is going to use.
If you are using following configuration in package.json
{
"scripts": {
"dev": "webpack -d --watch",
"build" : "webpack -p"
},
}
then webpack keeps watching any changes in .jsx file and update index.js
As you are saying you code is running without webpack.It means you are using simple .js file.But to use es6 or .jsx you need webpack.
Hope it helps!. For more you can read https://tylermcginnis.com/react-js-tutorial-1-5-utilizing-webpack-and-babel-to-build-a-react-js-app/

Resources