I am creating the UI component library in React...
My Webpack config have multiple entry points which result in multiple bundles eg:
Am using CommonsChunkPlugin which generates the common.js, which is shared code between other bundles.
In parent app (React app in which I want to consume UI lib) I do:
import { Button } from 'ui-library/lib/Button';
But this Results in:
webpackJsonp is not defined
Which means that common.js is not loaded. Here is my webpack plugins property value:
Am I missing something? IS common.js supposed to be loaded manually in the parent project? I expeted that importing the cmp is all which should be required, but maybe I am wrong, or I just missed something in the config...
Yes, you should import common.js manually, as stated in the documentation :
You must load the generated chunk before the entry point:
<script src="commons.js" charset="utf-8"></script>
<script src="entry.bundle.js" charset="utf-8"></script>
Source : https://webpack.js.org/plugins/commons-chunk-plugin/
Related
I've setup a new react app using npx create-react-app my-app.
In the index.html file I want to import a javascript file in the head like so
<script src="/src/.../file.js"></script>
However, I keep getting Unexpected token '<' error. I can't do an import as it creates loads of errors and I want to be able to use some functionality in these scripts across the site.
Any ideas how to reference this file? Previously in other projects we use webpack but this config doesn't seem available in this project.
If your js files are located in the /public/ folder then you can import it like this:
<script src="%PUBLIC_URL%/.../file.js"></script>
If it is located in /src/ folder, you can simply import it to your index.js file, and it will be available across your React application. Remember that order of imports matters here.
import './.../file.js';
What options are there to bundle an external javascript sdk into a React Component?
I have tried including the javascript in the index.html and referring to it through window.xyz . It works well but I can't do a production build since the javascript is not packaged in this way.
Is there a way to simply import a javascript file into the React Component definition?
PS: React Newbie here !
If you want the script to be bundled in the build, you have 2 options:
1. If the external file is a module, I would approach it as follows:
Download the external JS file and save it somewhere in the project. For example, save it to /utils folder.
Just reference it and use it in the components: import { test } from '/utils/external'
2. If it's not a module:
The same as above - save the file to your project.
The difference is that you have to configure your module bundler to export the globals. This process is called Shimming and here's how to do it with Webpack.
The same as step 2 - import { test } from '/utils/external'
* In both scenarios I assume it's a standalone external file, not being hosted somewhere as a package (npm / bower / etc.). If it's a package, instead of downloading it manually, you should use a package manager.
If you want to load it async (but not bundled):
Follow the #Paras answer, where he suggests for using a library for script async lazy loading.
To load external scripts from a CDN, a good option is to use the react-async-script-loader library. Not only can it load external JS files asynchronously, but it also loads on demand, i.e., lazy loading and supports both parallel and sequential loading.
It allows you to decorate your component using an HOC like so:
export default scriptLoader(
[
'https://cdnjs.cloudflare.com/somelibrary1.min.js',
'https://cdnjs.cloudflare.com/somelibrary2.min.js'
]
)(YourComponent)
Actually you should know about the entire approach then see the codes.
You must make a separate folder for your alternative cdn JavaScript files which they are out of files that webpack build them. Then paste these files into this folder and after all import them as externals into webpack configuration.
Then config them as vendor files, and absolutely output file name should make dynamically, so the webpack build its bundle and then copy your JavaScript files into dist folder. follow below:
// webpack.configuration.js
~~~
module.exports = {
~~~
externals: {
cdnFileOne: `${srcRoot}/outFiles/cdnFile1.js`,
cdnFileTwo: `${srcRoot}/outFiles/cdnFile2.js`,
},
~~~
};
Sounds good, now you have external names for JavaScript files and import it into webpack configuration as a externals config.
Now you should put them in entry to import them as separate files:
// webpack.configuration.js
~~~
module.exports = {
~~~
entry: {
cdnFiles: ['cdnFileOne', 'cdnFileTwo'], <-- cdn files
app: `${srcRoot}/app/index.js`, // <-- its your own codes
},
output: {
path: '/dist',
filename: '[name].js' // <== dynamically make your JavaScript files,
// so, in dist folder you can see app.js and
// cdnFiles.js file
}
~~~
};
Surly, you must add bundles to your HTML template:
~~~
res.status(200).send(`
<!doctype html>
<html lang="en">
<head>
<meta charSet="utf-8" />
${styles}
${title}
</head>
<body>
<div id="root">${ssrHTML}</div>
<script src="app.js" defer></script>
<script src="cdnFiles.js" defer></script>
</body>
</html>
`);
~~~
try something like this:
componentDidMount () {
const script = document.createElement("script");
script.src = "https://cdnjs.cloudflare.com/somelibrary1.min.js";
script.async = true;
document.body.appendChild(script2);
}
I have been pulling my hair out for 3 weeks trying to get this to work, and I can't figure out where the gap in my understanding is.
I am building a library of components for an authorable CMS. My vision is to have a set of n thin entrypoints, all of which will have statically imported dependencies that are requested when the entrypoint is run via script tag.
Per my understanding, webpack can chunk shared dependencies together via splitChunks plugin, and those dependencies can be automatically loaded via the bundle-loader plugin.
However, when I call an entrypoint bundle via script tag, the automatic dependency import does not occur - only when I use dynamic import() syntax within my source files does dynamic import occur - but that's because import() itself is dynamic.
How can I configure webpack to pull in statically dependent chunks?
Check out Paragons (see section: Code Splitting). Then take a look at CodeSplitPage which is wrapped in a Loadable using a dynamic import.
The HtmlWebpackPlugin is what you're looking for. You can configure it to generate entry.html output files in your dist folder, which you can then use in an Express application, or import into your non-Node server rendering to get the full list of <script> tag.
Context
I'm working on a project using Angular2, TS and SystemJS. I've built a simple module loader using SystemJS which allows me to import 'custom' modules like this :
import { NavComponent } from "component#nav";
Maybe it'll be important.
Goal
I would like to import .scss files inside my angular components to be able to do things like that :
#Component({
selector: 'app-view',
styles: [ require('path/to/mainScss/file.scss') ],
template: //...
})
Issue
I've found some examples using webpack but I can't get this works. During searching, I've found this module. It can be interesting because it uses SystemJS like me and I don't have to add webpack to my project.
So I've decided to use it (and I'm not sure if it's possible to use webpack and SystemJS at the same time. require was undefined). I didn't know jspm before using this module, I've always used npm. So I've installed jspm locally (relative to my project) and globally and I've installed the module.
Then, inside a component : import './styles/importer.scss!';. And I get an error here.
Error: SyntaxError: Unexpected token <. I know that this error happens when SystemJS failed to load a module but I can't figure out why.
Why ?!
Why am I trying to do that ?
My module loader allows me to write some modules in separate folders (named like this namepace#name). I can add those folders inside another one named modules/ and then enable/disable modules by editing a configuration file.
So I want my .scss files to be loaded only if a module is enabled. That's why I want to include my sass inside an Angular component. That way, it'll be loaded only if the component is loaded.
What is the current recommended practice for converting a library written in TypeScript to ES5?
JSPM documentation seems to be geared toward web apps (i.e. with jspm bundle-sfx).
All the articles I can find on Google seems to be assuming a web app workflow rather than a library workflow.
My projects have the following setup:
It depends on react, flux and jquery, all installed through jspm and are properly configured in config.js
The source .tsx/.ts files are located in a src/ tree, along with their corresponding transpiled .js files
I am able to create a bundle with jspm bundle, however, this still requires the end user of my library to be using SystemJS
What I want is to bundle the entire tree under src/ into a single file without libraries such as react or jquery. How can I do this?
So far I've tried jspm bundle src/<MY_MAIN.js> - react - jquery <OUT.js> this works, but user still need a module loader to interact with exported symbols in MY_MAIN.js. I would also like to provide users with an option to manually import my library with <script> tags. self-executed bundles do not seem to work. No symbol is accessible globally once loaded through the <script> tag and I cannot exclude the framework code.
There are basically three approaches that I want to highlight, targeted at different end-user workflows
1. the <script/> tag approach
Here, create an entry .ts file that exports the main symbols of the library like so:
// Main.ts
import {MyLib} from "./components/MyLib";
import * as React from "react";
import * as ReactDOM from "react-dom";
/**
* browser exports
* note, typescript cannot use interfaces as symbols for some reason, probably because they are not emitted in the compiled output
* running `jspm bundle-sfx` results in the code here being accessible in <script /> tag
*/
(function (window) {
window.MyLib = MyLib;
window.React = window.React || React;
window.ReactDOM = window.ReactDOM || ReactDOM;
})(typeof window !== "undefined" ? window : {});
then run jspm bundle-sfx Main.js my-lib.sfx.js, the same works for browserify, except we have to use commonjs style require() instead of ES6 style import
2. Concat & Minify src files through regular gulp/grunt
this should just be the good old workflow we are all familiar with
3. Assume ES6 compatibility for apps that will use the library
Distribute the code as ES6/TS along with .d.ts and assume the user will also use jspm/system or eventual ES6 module loader approach to load your module