Share Your Code with Others

The word counter we’ve built in the previous chapter executes as soon as the page loads. It’d be easier to integrate it in another application if we could decide when and where the word counter appears, without knowing how React works. To let others without React knowledge use your components in their own application, let’s adapt the webpack configuration to make the word counter a library.

If another developer wants to use your word counter library, they will probably expect to access the word counter through the Wordcounter global variable. They’d then assume that calling init should create the word counter on the element with app id. However, because of how things currently work, this will fail.

Try this out yourself so you can see it in action. In your word counter directory, place the following code in a new file named initialize.js:

 Wordcounter.init(
  document.getElementById(​'app'​)
 );

Then create a new HTML index page, name it index-library.html, and include initialize.js in a <script> tag before the closing <body> tag:

 <script src=​"initialize.js"​></script>

As you load the page and open the console, you’ll see the following error:

 Uncaught ReferenceError: Wordcounter is not defined

Let’s change how we package our word counter to fix this.

First, let’s create a new entry point for our code, so that developers can call a function on a DOM node to create a word counter on that node. Create a new file in the src directory and name it index-library.js.

In this file, export two functions: an init function that takes a DOM element and initializes the word counter on that element, and a destroy function to remove the word counter from the page. Import React, ReactDOM, and the WordCounter component:

 import​ React from ​'react'​;
 import​ ReactDOM from ​'react-dom'​;
 import​ WordCounter from ​'./WordCounter'​;
 
 export​ ​function​ init(element, target = 10) {
  ReactDOM.render(<WordCounter targetWordCount={target} ​/>, element​​)​​;
 }
 export​ ​function​ destroy(element) {
  ReactDOM.unmountComponentAtNode(element);
 }

init takes a DOM element and a target word count and renders a WordCounter element on the DOM element. destroy takes a DOM element and calls ReactDOM.unmountComponentAtNode to remove the editor from that node. We export each function separately.

Now we have two new entry points that let the user choose when and where to instantiate the word counter. Now we have to let users call our new functions through a global variable. webpack will take care of that part. Copy your existing webpack configuration to a new file named webpack.config.library.js. Open the new file and modify the entry point to point to index-library.js:

 module.exports = {
  entry: [​'./src/index-library.js'​],

Next, make init and destroy available on a global variable. In the output section, set libraryTarget to ’var’, and set library to the name of the global variable—in this case, ’WordCounter’. To distinguish the library bundle from the application, change the output file name to library-bundle.js:

 output​:​ {
  path: __dirname,
  filename​:​ ​'library-bundle.js'​,
  libraryTarget​:​ ​'var'​,
  library​:​ ​'Wordcounter'
 },

Now that we’ve made the necessary changes to the webpack configuration, create a new entry in package.json to run webpack with the new configuration. Open package.json and in the scripts section, insert the following script with the library:build key:

 "library:build"​​:
 "cross-env NODE_ENV=production webpack -p --config webpack.config.library.js"​​,

This code runs webpack, but instead of using the default configuration webpack.config.js, it uses webpack.config.library.js.

To test, run:

 $ ​​npm​​ ​​run​​ ​​library:build

When run, webpack outputs the library bundle to library-bundle.js.

Include library-bundle.js in index-library.html just above initialize.js:

»<script src=​"library-bundle.js"​></script>
 <script src=​"initialize.js"​></script>

Reload the page. Since the WordCounter variable is now defined and contains the init function, initialize.js manages to create the word counter.

With these changes, a developer who’s never heard of React can use the word counter, but if they use many of your components on the same page, the total file size will be huge, because we’re including the whole of React in every bundle. It would be more efficient to take React out of the components we distribute, and tell our fellow developer to load React on the page once via a separate <script> tag. Let’s make this possible by tweaking the webpack configuration a little more.

To exclude React and ReactDOM from the bundle, add a new section named externals below output in webpack.config.library.js. We’ll assume that the libraries will be available as global variables named React and ReactDOM, respectively:

 externals​:​ {
  react: ​'React'​,
 'react-dom'​​:​ ​'ReactDOM'
 },

We use the module name as the key, and the global variable name as the value. Here, the module name is react-dom, and the global variable name is ReactDOM.

Rebuild the library bundle:

 $ ​​npm​​ ​​run​​ ​​library:build

When the build completes, notice the file size of library-bundle.js has gone down quite a bit.

The new library bundle assumes that the React and ReactDOM global variables will exist on the page. Link React and ReactDOM from the CDN. In this case, use the links to the production versions of React and ReactDOM. As you learned in Chapter 1, An Introduction to Components, you should avoid the development versions in production because they run much slower. Insert the two <script> tags before the library bundle, and reload the page.

»<script src=​"https://unpkg.com/react@15/dist/react.min.js"​></script>
»<script src=​"https://unpkg.com/react-dom@15/dist/react-dom.min.js"​></script>
»<script src=​"library-bundle.js"​></script>
 <script src=​"initialize.js"​></script>

Now the word counter library works fine with React from the CDN.

Now you can distribute your React code so that others can use it in almost any web page. Next, let’s see how you can use almost any JavaScript code in your React apps.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.134.130