Adding foundation to webpack - reactjs

I have followed the official tutorial to set up react, typescript and webpack from here: https://www.typescriptlang.org/docs/handbook/react-&-webpack.html
Until this point it runs, fine.
Now I want to use the foundation CSS framework.
So I ran npm install --save foundation
Then I modified my TSX file to look like:
import * as React from "react";
import * as ReactDOM from "react-dom";
import * as React from "react";
import * as ReactDOM from "react-dom";
ReactDOM.render(
<a class="button" href="#">Default Button</a>,
document.getElementById("example")
);
Finally, I ran webpack.
However, when I open the generated index.html, the "button" is not there, just a link, which means the style was not applied.
In my /dist folder, I don't see anything related to css...
It seems that I'm missing something. Is there additional configuration that I have to do with webpack?

At first, foundation is installed as
npm install --save foundation-sites
then you need to include foundation in your root css file like
#import 'foundation';
and finally you need to alias it inside webpack config. For example when you are using sass loader
module: {,
sassLoader: {
includePaths: [
path.resolve(__dirname, "./node_modules/foundation-sites/scss")
]
}

Related

How to import ReactJS Material UI using a CDN through Webpack's externals?

The Problem:
I'm trying to create a website (web app) with React and Material UI, it's working just fine using npm. But when I try to make them as externals and import them through a CDN instead, I get an error with Material UI (React works fine).
My Code:
I linked CDNs in index.html like this:
<script src="https://unpkg.com/react#16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/#material-ui/core/umd/material-ui.production.min.js"></script>
<script src="app.min.js"></script>
And in app.min.js, I imported them like this:
import { Component } from 'react';
import ReactDOM from 'react-dom';
import { Button } from '#material-ui/core';
My Attempt:
In the webpack.config.js, I tried the following (again, only Material UI causes an error):
Using a string:
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'#material-ui/core': 'Button'
}
gives:
Uncaught ReferenceError: Button is not defined
Using an object:
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'#material-ui/core': {
Button: '#material-ui/core'
}
}
gives:
TypeError: Cannot read property 'Button' of undefined
Doing it manually, so Material UI isn't in externals:
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}
Then removing minified Material UI code from app.min.js, this leaves the code incomplete and it doesn't run.
Searched through GitHub issue and SO questions without any luck, some links:
How should material-ui be externalized when bundling with webpack
Externals defined in webpack.config still getting error module not found
React CDN: Webpack externals library not resolved in code
Any idea how can I solve this?
Solution::
in webpack.config.js:
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'material-ui': 'window["material-ui"]'
},
then in app.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Button } from 'material-ui';
Explanation:
If you check the cdn version of material ui js, you will find it exports its content in to material-ui namespace.
if you config webpack like:
'material-ui': 'material-ui'
webpack will compile it to:
which leads to the code looking for material and ui in global environment which does not exist. So we have to specify window["material-ui"] explicitly
Might be a little late to the party but I will add an answer which worked for me.
step 1:
add the script tag from unpkg. The difference between this and cdnjs is that unkpg have an option for umd. May or may not be an issue in your particular situation. It is for me.
url:
https://unpkg.com/#material-ui/core#4.11.0/umd/material-ui.production.min.js
script tag:
<script src="https://unpkg.com/#material-ui/core#4.11.0/umd/material-ui.production.min.js"></script>
step 1b:
add the font and font icon external resources as described in the material-ui docs:
material-ui getting started - installation guide
roboto font:
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
font icons:
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
step 2:
destructure the elements you want to use from window.MaterialUI or use the square bracket notation (but unnecessary here since this package ditched the '-' char.
const { Button } = window['MaterialUI'];
step 3:
use the element as you 'normally' would
<Button variant="contained" color="primary">
Primary
</Button>
I have just solved this issue after spending way too much time on this issue while trying to build an app using a micro-frontend architecture.
TL;DR;
The solution is to put the following in the webpack.config.js:
module.exports = {
// rest of the config clipped for brevity
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'react-router-dom': 'ReactRouterDOM',
'#material-ui/core': 'MaterialUI'
}
};
Further details:
I was building a macro-frontend composed of multiple micro-frontends. Each of the micro-frontends was developed in React, exported as a web-component, and would be independently deployed such that each micro-frontend would be available via a URL like:
http://foo.example.com/main.js
http://bar.example.com/main.js
http://baz.example.com/main.js
These would be imported into the macro-app using a <script> tag.
The macro-app was hosted on a separate domain, e.g., http://example.com.
The issue I was facing was that Material UI (and possibly React as well) was being initialized multiple times in each of the micro-apps.
To avoid that, I had to externalize all these libraries using the webpack config block above.
I had to make 2 concessions.
I did not use create-react-app and react-scripts to scaffold the macro-app because that setup would hide the webpack config. In order to expose the webpack config, I could either eject the CRA project, or use some other modules, such as react-app-rewired, etc. That felt like too much work. The downside of this was that I could not use BrowserRouter and had to accept using HashRouter for client-side routing.
I could not use SvgIcon-based icons from #material-ui/icons, because I could not find a good way of externalizing Material UI Icons. Instead, I put in a link to Material UI Icons stylesheet, and opted to use Icon from #material-ui/core/Icon to render icons. using SvgIcon-based icons was causing Material UI to be initialized in the micro-apps too, which is what I was trying to avoid. One upside of the workaround is that Icon works with Font Awesome as well, so at least all icons would be written consistently in code.
Overall, I am happy with the end results.

react-virtualized, SystemJS and CDN

I would like to use react-virtualized in a web application via cdnjs and SystemJS.
From all the examples that I have seen, it seems that react-virtualized and react libs are loaded locally, then bundled with Webpack before being included in a web page. Now I would like to use it via cdnjs without Webpack by simply importing it with SystemJS. But when I tried that I am getting errors saying that it can't find React.
I was wondering if anyone has tried this before, and whether this is supported at all by react-virtualized. Thanks.
UPDATE:
For clarity, I have included some code to show what I am trying to do.
index.html:
...
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.20.0-alpha.1/system.js"></script>
<script>
System.config({
map: {
"react":"https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.js",
"react-dom":"https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.js",
"react-virtualized":"https://unpkg.com/react-virtualized/dist/umd/react-virtualized.js"
}
</script>
</head>
...
main.jsx:
import React from 'react';
import ReactDOM from 'react-dom';
import {Table, Column} from 'react-virtualized';
...
What you are doing is possible using the UMD build of react-virtualized. You can see an example of that being done here. In order for it to work though, you'll need to also import UMD builds of react-with-addons and react-dom since react-virtualized depends on them.
For example:
<script src="https://unpkg.com/react/dist/react-with-addons.min.js"></script>
<script src="https://unpkg.com/react-dom/dist/react-dom.min.js"></script>
<script src="https://unpkg.com/react-virtualized/dist/umd/react-virtualized.js"></script>
The react-virtualized UMD build expects React and ReactDOM to be loaded in the global space.
Alternately there should be a way with SystemJS to expose react-dom and react-with-addons as globals for libraries like react-virtualized to consume. I'm not a SystemJS user, but I think it might be something like this:
System.config({
meta: {
'path/to/react-virtualized.js': {
globals: {
React: 'path/to/react-addons-shallow-compare.js',
ReactDOM: 'path/to/react-dom.js'
}
}
}
});
It's been a while, but I had some time to look at this again. Thanks to #brianvaughn's suggestion, I have managed to resolve this with the following:
System.config({
meta: {
"react-virtualized": {
exports: "ReactVirtualized",
format: "global",
globals: {
React: "react",
ReactDOM: "react-dom"
}
}
},
map: {
"react": "https://unpkg.com/react#16/umd/react.production.min.js",
"react-dom":"https://unpkg.com/react-dom#16/umd/react-dom.production.min.js",
"react-virtualized":"https://cdnjs.cloudflare.com/ajax/libs/react-virtualized/9.10.1/react-virtualized.min.js",
}
})
main.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import * as ReactVirtualized from 'react-virtualized';
let Table = ReactVirtualized.Table;
let Column = ReactVirtualized.Column;
let AutoSizer = ReactVirtualized.AutoSizer;
...

Angular modules import with webpack - Argument 'module' is not a function, got Object

I've been trying to setup angular 1 with webpack and ran into an issue with import modules, let's say I want to import ramda from node_modules
import angular from 'angular';
import uirouter form 'angular-ui-router';
import routing from './app.config';
import * as ramda from 'ramda';
angular.module('app', [uirouter, ramda])
.config(routing);
I get an error: Argument 'module' is not a function, got Object. If I console ramda, it is indeed an object and I understand I need a string, but I just couldn't figure out how to get it?
Change it to import ramda from"ramda".
This is because the export of the module is the module name.
When you write import * as ramda you import the namespace object, which is an object containing all the exports of that module.
If you are using TypeScript, you may need to add a allowSyntheticDefaultImports to your tsconfig.json.
allowSyntheticDefaultImports

ng2-bootstrap module in visual studio 2015

I'm trying to import ng2-bootstrap module in VS project.
I fetch this github repo and it start successfully after adding "moment": "2.11.2" to tsconfig.json.
In VS I do almost the same, adding "ng2-bootstrap": "1.0.5", "moment": "2.11.2" to tsconfig.json, VS restoring it to Dependencies. Then with gulp I move ng2-bootstrap.min.js, moment.js to root app directory and bundle it to index.html and moment.js map in system.js configuration as map: { moment: 'libs/moment.js }.
After adding Alert component to my angular class:
import {Component, OnInit} from 'angular2/core'
import {Router} from 'angular2/router'
import {HeroService} from './hero.service'
import {User} from './user'
import {Alert} from 'ng2-bootstrap/ng2-bootstrap'
//declare var jwt_decode: any;
#Component({
selector: 'login',
templateUrl: 'app/login.component.html',
styleUrls: ['app/login.component.css', 'app/css/bootstrap.css', 'app/css/styles.css'],
directives: [Alert]
})
After build I take a following error:
Error TS2307 Build: Cannot find module 'moment'. ASPAngular2Test E:\Development\C#\ASP.NET\ASPAngular2Test\src\ASPAngular2Test\node_modules\ng2-bootstrap\components\datepicker\date-formatter.ts 1
I insert this <script src="libs/moment.js"></script> into my index.html
and declare a variable in date-formatter.ts like declare var moment: any, error is gone, but after bulding bootstrap tags has no effect.
Project Solution Structure
And in mysterious way i get compiled node_modules/ng2-bootstrap and my all ts files in wwwroot/app/scripts directory. I replaced compiled js files in wwwroot/app/and it's also has no effect. My application don't see native properties of ng2-bootstrap components. Maybe someone faced with this sort of problem?
you are adding ng2-bootstrap to tsconfig.json?
Shouldn't it be added to package.json?

angular-timer with webpack

I tried using angular-timer with webpack, es6 and the npm modules of moment and humanize-duration
My implementation would be:
import 'moment';
import 'humanize-duration';
import 'angular-timer';
And I get the error ReferenceError: humanizeDuration is not defined.
Sure, angular-timer needs the variable humanizeDuration and suggests in the requirements section to use bower and script src. In my understanding importing the src with webpack is the same as using it as src in a script tag.
This help for me:
Install moment and humanize-duration:
$ npm install moment
$ npm install humanize-duration
Install them in your webpack.config.js as plugins:
module.exports = function makeWebpackConfig() {
/**
* Config
* Reference: http://webpack.github.io/docs/configuration.html
* This is the object where all configuration gets set
*/
var config = {};
config.plugins = [
new webpack.ProvidePlugin({ 'moment': 'moment', 'humanizeDuration': 'humanize-duration' })
];
And import angular-timer in your component
import 'angular';
import 'angular-timer';
let yourModule = angular.module('your', [
'timer'
]);
I hope this will help you

Resources