Bootstrap Material Design with Webpack - reactjs

perhaps a really rookie webpack question, but here i go:
Was wondering (since i really havent found any direct answers) if anyone could give me a hint on how to get bootstrap material design working? I get the css stuff going for me but not the ripples.js stuff...
my webpack setup, well bits of it:
...
plugins: [ new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery" }) ],
module: {
loaders: [
{ test: /\.js?$/, exclude: /(node_modules|bower_components)/, loader: 'babel' },
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
{ test: /\.(woff|woff2)$/, loader:"url?prefix=font/&limit=5000" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" }
]
}
...
in my react's index.js which is where it all starts:
...
import Bootstrap from 'bootstrap/dist/css/bootstrap.css'
require('bootstrap-material-design/dist/css/bootstrap-material-design.css')
require('bootstrap-material-design/dist/css/ripples.min.css')
...
how would i get the material.js and ripples.js to work?
i get no console errors or webpack errors, but the darn ripples are not showing! i am guessing there is a smart webpack way to get this all running or do i need to require the .js explicitly in my index.js (that has not worked)?
thanks in advance,
hanto899
UPDATE:
if i require the following in my index.js file:
require('bootstrap/dist/css/bootstrap.css')
require('bootstrap-material-design/dist/css/bootstrap-material-design.min.css')
require('bootstrap-material-design/dist/css/ripples.min.css')
require('bootstrap')
var material = require('bootstrap-material-design/dist/js/material.js') // not sure if the "var material =" is necessary here...
var ripples = require('bootstrap-material-design/dist/js/ripples.js') // not sure if the "var material =" is necessary here...
let $ = require('jquery')
$.material.init()
i get no errors, but ripple doesnt work. but... if i navigate to another page, and add, while on that page, :
let $ = require('jquery')
$.material.init()
webpack hot-reloads and then i get the ripple working. howerver if i refresh the page, i get:
Uncaught TypeError: Cannot read property 'init' of undefined
....

Finally, I got it working.
You can simply import them as follows
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-material-design-master/dist/css/bootstrap-material-design.css";
import "bootstrap-material-design/dist/css/ripples.css";
import "bootstrap-material-design-master/dist/js/material.js";
import 'bootstrap-material-design-master/dist/js/ripples.js';
Then you need to call
$.material.ripples()
$.material.ripples() will apply ripples.js to the default elements.

Above answer by #MrJSingh and #Rob Kielty was not working for me.
So, I did some necessary modifications. Hope this will help.
In your entry point file (i.e. index.js in my project), import the files as follows
import '!style-loader!css-loader!bootstrap/dist/css/bootstrap.min.css';
import '!style-loader!css-loader!bootstrap-material-design/dist/css/bootstrap-material-design.min.css';
import '!style-loader!css-loader!bootstrap-material-design/dist/css/ripples.min.css';
import 'bootstrap-material-design/dist/js/material.min.js';
import 'bootstrap-material-design/dist/js/ripples.min.js';
Then call
$.material.init();
Find my webpack configuration is here

Related

Why doesn't storybook use the same webpack config as in the project?

I have been using storybook for a while now but I still couldn't understand the reason behind storybook has its own webpack config.
For example, if I config an absolute path in tsconfig.json, I have to do the same thing for storybook.
Or if I want to use a loader for a file type, I have to do it again for storybook and it's kind of annoying.
Can anyone explain this or how did you overcome this hassle in your previous projects?
#nishkaush I have to post a comment for you to read. So I did resolve that (loader for svg) even it took a lot of my time. Take a look if you're interested.
webpackFinal: async (config) => {
const fileLoaderRule = config.module.rules.find(
(rule) => rule.test && rule.test.test('.svg'),
)
fileLoaderRule.exclude = /\.svg$/
config.module.rules.push({
test: /\.svg$/,
enforce: 'pre',
loader: require.resolve('#svgr/webpack'),
})
return config
},
You can put that in your storybook webpack config (main.js)
And this one for project webpack config:
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
issuer: {
test: /\.(js|ts)x?$/,
},
use: ['#svgr/webpack'],
})
return config
},
Don't forget to install #svgr/webpack
I was having the same issue today. Storybook's webpack config uses SVG-loader whereas my webpack config uses file-loader.
So, even though using an SVG as an img's src worked for my project, it didn't work for Storybook.
Really annoyed me.
Had to re-write all my icons that were using img tag to use inline SVG. Wasted Afternoon!

React npm package: Do I need a different webpack config to be ssr safe?

I maintain a small npm package and I am currently trying to use it in a Gatsby site. I am not a webpack expert and I am struggling to make my npm package ssr safe.
Currently, if I try gatsby build it will throw the following error:
failed Building static HTML for pages - 0.829s
WebpackError: ReferenceError: window is not defined
componentDidMount = () => {
window.addEventListener( 'click', this.onClickCloseMenu, false );
}
I added the following file to my package:
// allows us to use window server-side
const safeWindow = (typeof window === 'undefined') ? {
addEventListener() {},
removeEventListener() {},
} : window;
export default safeWindow;
and imported the object in my code:
import safeWindow from './safeWindow';
...
componentDidMount = () => {
safeWindow.addEventListener( 'click', this.onClickCloseMenu, false );
}
But unfortunately this didn't help. I was already using window only in useEffect/componentDid(Un)Mount but I guessed since it was a compilation error that I needed to define it. My next guess is that building/minifying my package to publish it to npm broke this again but I am not sure.
This is my webpack config:
var path = require('path');
module.exports = {
mode: 'production',
entry: './src/DataListInput.jsx',
output: {
path: path.resolve('lib'),
filename: 'DataListInput.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: 'babel-loader'
},
{
test: /^(?!.*?\.module).*\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.module\.css$/,
use: ['style-loader', {
loader: 'css-loader',
options: {
modules: true
}
}]
}
]
}
}
Any help is highly appreciated!
Find the npm package here
UPDATE
I am pretty sure now that it has something todo with webpack bundling css together with javascript in the minified file which requires calls to both window and document. Does someone has experienced something similar? How do I solve this issue?
UPDATE 2
I resolved the issue by removing the css. I created a new ssr safe npm package without css. It feels more like a work-around than a solution, so I am still interested if there is a way to bundle css + javascript and be ssr compatible.
Changing safeWindow from a constant into a getSafeWindow function should fix it.
A constant is evaluated before the module can be imported. While a function version will only access window when it is called at runtime.
const getSafeWindow = () => (typeof window === 'undefined') ? {
addEventListener() {},
removeEventListener() {},
} : window;

CSS-modules with storybook module not found

I've installed in my react project storybook v5. Everything seems to be ok, but when I want to import styles to my react component (I use postcss-modules) I have an error Module not found: Error: Can't resolve './styles/Buttons'.
What should I add to storybook config to make it workable? I use babel in my project.
You need to customize Storybook’s webpack set up by adding webpack.config.js.
For example adding SASS:
// # webpack.config.js
const path = require('path');
// Export a function. Accept the base config as the only param.
module.exports = async ({ config, mode }) => {
// `mode` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
// Return the altered config
return config;
};
Check out the docs.

How to use react as a component library rather than application

I'm trying to learn react and also introduce it in already existing project. Thus I want to use react in a few places where it makes sense, instead of using it everywhere.
The problem is the entry-point concept that I can't wrap my head around. I'd prefer to have:
ReactDOM.render(
<MyComponent/>,
document.getElementById("componentExample")
);
inside my cshtml near <div id='componentExample'></div> rather than in a separate jsx. I understand that I can't use jsx syntax in cshtml, but if I write
<script src="#Url.Content("~/Scripts/dist/bundle.js")"></script>
<script>
ReactDOM.render(
React.createElement(MyComponent, {}, null), document.getElementById("componentExample")
);
</script>
This doesn't really work because MyComponent is undefined. It is included in my bundle.js (I had to add it as entry point), but it is inside the scope of some webpack stuff and is not exposed.
What is the proper way of doing this?
My goal is to write some components for my app where it is more suitable and use it here and there, without completely going into react-based architecture.
My setup is webpack + babel polyfill + typescript + react and this is in ASP.NET MVC.
My webpack.config.js is:
var config = {
entry: ['babel-polyfill', "./SiteScripts/React/index.tsx", "./SiteScripts/React/Components/MyComponent.tsx"],
output: {
filename: "./Scripts/dist/bundle.js",
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
rules: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
enforce: 'pre',
test: /\.js$/,
loader: "source-map-loader"
},
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
{
test: /\.tsx?$/, loaders: ['babel-loader', "ts-loader"], exclude: /node_modules/
}
]
},
plugins : []
}
if (process.env.NODE_ENV === "production") {
config.devtool = "cheap-module-source-map";
}
module.exports = config;
Also this is somewhat related to the question (as question about architecture): I'd like to make my bundle.js smaller - it is 30k lines now. It is probably because I'm trying to use react in a wrong way?
I finally found the problem. I had a few mistakes (and didn't completely understand the whole theory behind webpack) and the answer is definetely beyound the code I gave in the question - so I do not have any answers.
First I had to make by bundle a library, in order to export stuff defined in it (webpack.config.js):
entry: ['babel-polyfill', "./SiteScripts/React/index.tsx"],
output: {
filename: "./Scripts/dist/bundle.js",
libraryTarget: "var",
library: "WebPack"
},
This will make types/variables defined in index.tsx (I think only last file from entry list is taken) and that are exported - available via WebPack.<name>
I needed to export my component. I've done it like this - but there are probably better ways (index.tsx):
import { MyComponent} from "./Components/mycomponent";
export var myComponent = MyComponent;
I also needed to ensure all my subcomponents are modules. This means using import everywhere, and adding a keyword export to all element, props and states.
After that I was able to render my component from:
<script src="#Url.Content("~/Scripts/dist/bundle.js")"></script>
<script>
ReactDOM.render(
React.createElement(WebPack.myComponent,
{
PropA = 2, PropB = "3"
}, null),
document.getElementById("componentExample")
);
</script>
One more thing to watch for if I am doing this is that the line <script src="#... does not happen more than once in my result html (this is very likely as I am using many components embedded in a single page). I use this javascript function to ensure I load bundle.js only once:
function loadJsOnce(url, whenFinish) {
if (!window.loadedScripts) {
window.loadedScripts = {};
}
if (!window.loadedScripts[url]) {
var script = document.createElement('script');
//script.async = true; // remove this if you don't want the script to be async
script.src = url;
script.onload = function() {
whenFinish();
}
document.getElementsByTagName('head')[0].appendChild(script);
window.loadedScripts[url] = true;
} else {
whenFinish();
}
}
In url I specify the path to bundle.js and in whenFinish function I put a function that calls ReactDOM.render(... stuff

How to get ReactJs to integrate with Webpack?

Basically, I have just been through this simple tutorial, and now I want to get it to use React so I can see that display.
When I had this code:
module.exports = "It works from.js.";
It worked fine. But now I have this:
var React = require('react');
var ReactDOM = require('react-dom');
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
);
}
});
ReactDOM.render(
<CommentBox />,
document.getElementById('content')
);
and it is complaining at line 9 point at the unexpected token < and I need an appropriate loader. anyone know what this loader may be?
thanks
Yeap, you are right you need babel-loader for your JSX code. Also if you use ES6 syntax with React you also need babel-core & babel-preset-es2015 & babel-preset-react npm's modules. After that incude all of them into your webpack.config.js file as below:
module.exports = {
//.. some stuff before
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loaders: ["babel"],
query: { presets: ['es2015','react'] }
}]
}
//.. another stuff
}
Also i leave a link for you, with tutorial how to use ise.
I hope it will help you.
Thanks

Resources