react, meteor, webpack, es6. How to create a loading/splash screen - meteor

I am using a build for react, es6 modules and meteor with webpack. These techs take a while to load all their stuff, before something shows up on the page. How can I with this stack show a pre-loader / splash screen while all this loads up?
my webpack file:
var autoprefixer = require('autoprefixer');
module.exports = {
entry: [
'babel-polyfill',
'./entry'
],
resolve: {
extensions: ['', '.js', '.jsx', '.json','css','scss']
},
devtool: 'eval',
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
plugins:['transform-runtime'],
presets:['es2015','stage-0','react']
}
},
{
test: /\.scss$/,
loader: 'style-loader!css-loader!sass-loader!postcss-loader'
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'url?limit=8192',
'img-loader'
]
},
]
},
postcss: [ autoprefixer({ browsers: ['last 2 versions'] }) ]
};
My entry.js file:
import '../store.js';
import './../lib/routes.jsx';
My routes.jsx file:
import React from 'react';
import {FlowRouter} from 'meteor/kadira:flow-router';
import {mount} from 'react-mounter';
import $ from 'jquery';
import store from '../store.js';
import {Provider} from 'react-redux';
import App from '../client/components/app/app.jsx';
import HomePage from '../client/components/pages/home/homePage.jsx';
import AboutPage from '../client/components/pages/about/aboutPage.jsx';
import BlogPage from '../client/components/pages/blog/blogPage.jsx';
import BlogPostPage from '../client/components/pages/blogPost/blogPostPage.jsx';
FlowRouter.route('/', {
name:"home",
action() {
mount(App, {page: <Provider store={store}><HomePage /></Provider>});
}
});
FlowRouter.route('/about', {
name:"about",
action() {
mount(App, {page: <Provider store={store}><AboutPage /></Provider>});
}
});
FlowRouter.route('/blog', {
name:"blog",
action() {
mount(App, {page: <Provider store={store}><BlogPage /></Provider>});
}
});
FlowRouter.route('/blog/:slug', {
name:"blog post",
action(params) {
console.log(params);
mount(App, {page: <Provider store={store}><BlogPostPage slug={params.slug} /></Provider>});
}
});
// this is just a work around for a problem I am having with initial rout loading in development mode.
if (!$('.app-root').length)
FlowRouter.go(window.location.href.replace(/^http(s)?\:\/\/[^:\/\#]*(\:[^\/\#]*)?\/?/,'/').replace(/\#.*$/,'')+'#'+Math.floor(Math.random()*100000));
let lastPage = FlowRouter.current();
store.subscribe(()=>{
let state = store.getState();
if (!state || state.currentURL != lastPage)
FlowRouter.go(state.currentURL);
});

After a ton of research and a lot of help from this thread: https://github.com/webpack/webpack/issues/215
I have discovered that there is no reliable way to do this, at least not what I had in mind.
The solution I used in the end was in my entry file to use the following code:
import $ from 'jquery';
$('body').addClass('css-loading-class-goes-here');
require.ensure(['../store.js', './../lib/routes.jsx'], function(require) {
require(['../store.js','./../lib/routes.jsx']);
});
You can add css, append content or whatever else you want to do at the start there, but this will only execute after alot of the 'native' javascript from webpack and friends has loaded (about 350kb in my case). Then the require.ensure enforces webpack to load all my app specific javascript in a seperate bundle after the fact, so my 'loader' is at lest active for half of the load process.
This was the only solution that I could find in the end.

Related

TailwindCSS 3.0 Upgrade overriding button styles

Problem:
Button class being overridden by default tailwind base classes. Not sure why my classes on the element aren't being applied.
Question:
How can I get my styles to apply properly?
Screenshot:
As you can see background color on .documentCategory__row is being overridden by button, [type=button] on index.scss which is being defined within #tailwind/base.
/* index.scss */
:root {
--color-primary: #00a3e0;
--color-secondary: #470a68;
--color-success: #87d500;
--color-accent: #e87722;
/* Dark themes below */
--color-dark-primary: rgba(31, 41, 55, 1);
--dark-text: rgba(187, 193, 198, 1);
}
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
I'm not sure if this has to do with me switching to dart-scss so here is my webpack configuration in case I am missing something
import path from 'path'
import { Configuration as WebpackConfiguration, HotModuleReplacementPlugin } from 'webpack'
import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'
import ESLintPlugin from 'eslint-webpack-plugin'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
const CopyPlugin = require('copy-webpack-plugin');
interface Configuration extends WebpackConfiguration {
devServer?: WebpackDevServerConfiguration;
}
const config: Configuration = {
mode: 'development',
devServer: {
static: path.join(__dirname, 'build'),
historyApiFallback: true,
port: 4000,
open: true,
hot: true,
},
output: {
publicPath: '/',
},
entry: './src/index.tsx',
module: {
rules: [
{
test: /\.(ts|js)x?$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'#babel/preset-env',
'#babel/preset-react',
'#babel/preset-typescript',
],
},
},
},
{
test: /\.(sa|sc|c)ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'postcss-loader', // postcss loader needed for tailwindcss
options: {
postcssOptions: {
ident: 'postcss',
plugins: [tailwindcss, autoprefixer],
},
},
},
],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader',
options: {
outputPath: '../fonts',
},
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
}),
new HotModuleReplacementPlugin(),
new CopyPlugin({
patterns: [
// relative path is from src
{ from: 'public/images', to: 'images' },
],
}),
// Add type checking on dev run
new ForkTsCheckerWebpackPlugin({
async: false,
}),
// Add lint checking on dev run
new ESLintPlugin({
extensions: ['js', 'jsx', 'ts', 'tsx'],
}),
],
devtool: 'inline-source-map',
};
export default config
If there are other files I am missing that are needed let me know!
without seeing what your index.tsx looks like I can only make a guess, but here's what caused this issue in our app:
in our index.tsx we were importing index.css after importing our component tree with import App from 'src/App. thus the css was loaded into the site in the wrong order. imports from components first (css modules, normal css imports), tailwind last.
go to your entry file (probably index.tsx) and try moving your import 'index.scss' line above importing the root component.
like this for example
/* index.tsx */
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'; // this file holds all tailwind styles
import { App } from 'src/App';
// ...
read more here:
https://github.com/tailwindlabs/tailwindcss/discussions/7304#discussioncomment-2256226
Even i faced the same issue but I am using Vue3 + element-ui-plus, after spending more than 6 hours my solution is to set :native-type='null':
<el-button type='primary' round #click='handleClick' :native-type='null'>Click Me</el-button>
but this is kinda "hack", this either need to be fixed by Tailwind or by element-ui team. Anyhow, for now enjoy ;)
And the discussion is on here
I got the same issue using tailwindcss v3 and NextUI, and button's background were "transparent". By adding type = {null}, to button's I solve the issue

How to import css with webpack?

TWO PART QUESTION
My steps:
Created empty folder
opend cmd
navigate to folder and run npm init -f
run vue init webpack
run npm install
npm i bootstrap-vue
npm run dev
my main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.use(BootstrapVue);
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
webpack.base.conf.js:
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production' ?
config.build.assetsPublicPath : config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': resolve('src'),
}
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{ //this rule will only be used for any vendors
test: /\.css$/,
loaders: ['style-loader', 'css-loader'],
include: [/node_modules/]
},
{
test: /\.css$/,
loaders: ['to-string-loader', 'css-loader'],
exclude: [/node_modules/] //add this line so we ignore css coming from node_modules
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
}
}
when I run this I get:
Module build failed: Unknown word (5:1)
Part 2:
After some time found a solution to the above problem by installing a loader package and changin my main.js to this:
import Vue from 'vue'
import App from './App'
import router from './router'
import '!style-loader!css-loader!bootstrap/dist/css/bootstrap.css';
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
this solved my first problem BUT:
If i try to add a local css file like so:
import Vue from 'vue'
import App from './App'
import router from './router'
import '!style-loader!css-loader!bootstrap/dist/css/bootstrap.css';
import './content/bootstrapGrid.css'
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
I again get the same error:
Module build failed: Unknown word (5:1)
I am new to webpack, vue and the entire SPA.
Been at this for a while now and im stuck, anyone that can see what I am missing?
!css-loader
This is the plain css loader. It will return the css code interpreting the resources inside, but it will not add it to the page.
With this loader #import and url(...) are interpreted like require() and will be resolved.
!style-loader
This loader adds CSS to the DOM by injecting a or tag.
To inject a you need to get the content of the css file, and then inject that.
require("style!raw!./file.css");
// => add rules in file.css to document
But it’s recommended to combine it with the css-loader, as it will interpret all the resources in your css file, instead of just having the raw css. (Check)
require("style!css!./file.css");
// => add rules in file.css to document
If you want to add a to your css file, you need to first have the url to that file, for that you can use the file-loader.
require("style/url!file!./file.css");
// => add a <link rel="stylesheet"> to file.css to document
Hope this helps!
Refer: css-loader, style-loader
A good article on this here

How to load css in react app?

I created a react app using create-react-app and everything works fine except that I can't figure out how to load css/stylus files.
In my previous react project that wasn't created using create-react-app I used webpack.config but now I don't know where to include this file and how to use it.
This is my folder structure:
.
+--client
| +--node_modules
| +--public
| +--src
| +--package.json
+--server
| +--node_modules
| +--src
| +--.babelrc
| +--package.json
This is my previous webpack.config.dev.js file:
import path from 'path';
import webpack from 'webpack';
export default {
entry: [
'webpack-hot-middleware/client?reload=true',
path.join(__dirname, '/client/index.js')
],
output: {
filename: 'bundle.js',
path: '/',
publicPath: '/'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [
{
test: /\.js$/,
include: path.join(__dirname, 'client'),
loader: 'babel-loader',
},
{
test: /\.styl$/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
},
],
},
{
test: /\.css?$/,
use: [
'style-loader',
{
loader: 'css-loader',
},
],
},
],
},
resolve: {
extensions: [ '.js', '.styl' ]
}
}
Please let me know if I need to provide additional information.
There is detailed informations about how to add SCSS and Less files to create-react-app project on their documentation. You can check here for more detail.
You can add basic CSS styling with just importing the file like shown below;
import '/css/main.css';
Or you can add as classNames
const styles = {
header: {
fontSize: 18,
color: '#909090',
}
};
export default class Header extends React.Component {
render() {
return (
<h1 className={styles.header}>This is a header</h1>
);
}
}
One of the approaches involves loading CSS files (via css-loader) from your JS files, for a Text.jsx
import React from 'react';
import './screen.css'; // if screen.css is located next to Text.jsx
class Text extends React.Component {
// ...
}
export default Text;
You could also generate an output CSS, using e.g. ExtractTextPlugin (see Webpack2 loading and extracting LESS file)

"Unresolved variable" when using className={styles.nameOfClass}

I am attempting to change a button's style in ReactJS with the "className" element. However, I get back an error stating "Unresolved variable nameOfClass" in WebStorm, and the stylistic changes are not made when I run webpack and open the page on localhost. I have attempted different methods of importing the CSS file and naming conventions to no avail.
The file with the React Component class is here:
import * as React from "react";
var styles = require('./Roster.css');
export class Roster extends React.Component<{},{}> {
render() {
return (
<div>
<button className={styles.nameOfClass} type="button" >Players</button>
</div>
);
}
}
And the Roster.css file is here:
.nameOfClass {
background-color: #ff0000;
}
webpack.config.js
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "./dist/bundle.js",
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
externals: ['axios'],
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
{ test: /\.tsx?$/,
loader: "ts-loader"
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),
}
],
preLoaders: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new ExtractTextPlugin('styles.css', { allChunks: true })
],
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};
You don't have to require the styles file.
import * as React from "react";
export class Roster extends React.Component<{},{}> {
render() {
return (
<div>
<button className="nameOfClass" type="button" >Players</button>
</div>
);
}
}
and your css file:
.nameOfClass {
background-color: #ff0000;
}
Should look something like:
import * as React from "react";
export class Roster extends React.Component<{},{}> {
render() {
return <div>
<button className="nameOfClass" type="button">Players</button>
</div>
}
}
You can't require css files, only typescript/javascript files.
There's the css-modules thing, and there are some js solutions for react/css, such as Radium and reactCss.

How to import css file for into Component .jsx file

I am trying to use the react-day-pickers component like so but I can't figure out how to import the .css file and I keep getting the error:
Module parse failed:
/Users/qliu/Documents/workspace/AppNexus/pricing_ui/contract-ui/app_contract-ui/node_modules/react-day-picker/lib/style.css Unexpected token (3:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (3:0)
I have "css-loader": "^0.19.0", in my package.json installed and
here is my Calender.jsx file:
import React from "react";
import DayPicker, { DateUtils } from "react-day-picker";
import "../../../node_modules/react-day-picker/lib/style.css"; // <==== ERROR ON THIS LINE
export default class Calender extends React.Component {
state = {
selectedDay: null
};
handleDayClick(e, day, modifiers) {
if (modifiers.indexOf("disabled") > -1) {
console.log("User clicked a disabled day.");
return;
}
this.setState({
selectedDay: day
});
}
render() {
// Add the `selected` modifier to the cell of the clicked day
const modifiers = {
disabled: DateUtils.isPastDay,
selected: day => DateUtils.isSameDay(this.state.selectedDay, day)
};
return <DayPicker enableOutsideDays modifiers={ modifiers } onDayClick={ this.handleDayClick.bind(this) } />;
}
}
and this is my webpack.config.js:
var path = require('path');
var webpack = require('webpack');
var settings = require('./src/server/config/settings');
var LessPluginAutoPrefix = require('less-plugin-autoprefix');
module.exports = {
devtool: '#source-map',
resolve: {
extensions: ['', '.jsx', '.js']
},
entry: [
'webpack-hot-middleware/client',
'./src/client/index.jsx'
],
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
// to avoid duplicate import of React with react-addons-css-transition-group
'./React': 'React',
'./ReactDOM': 'ReactDOM',
config: 'config'
},
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
lessLoader: {
lessPlugins: [
new LessPluginAutoPrefix({ browsers: ['last 2 versions'] })
]
},
module: {
loaders: [{
test: /\.(js|jsx)$/,
loaders: ['babel'],
exclude: /node_modules/
},
{
test: /\.less$/,
loader: 'style!css!less'
},
{
test: /\.json$/,
loader: 'json-loader'
}]
}
};
How are you compiling this? If it's webpack, you'd probably need to bring in the style-loader and include something like this in the module.loaders array in your webpack config:
{
test: /\.css$/,
loader: "style!css"
}
Update: With the webpack.config.js now provided, we can confirm it needed a change in the module.loaders array. OP was using a less loader and only checking for .less files, so the exact loader object should read:
{
test: /\.(less|css)$/,
loader: 'style!css!less'
}
As suggested by #Q Liu. Leaving the original bit as if someone comes here with an error importing a .css file, it's likely what they need.
I used the following in my webpack config and it worked:
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
JSX is not CSS. In your main HTML file, just add a <link> element to the CSS file, and the DOM generated by React will use it.

Resources