简体   繁体   中英

Using Webpack externals and still allow ES6 style imports?

I'm creating a Chrome Extension and I'm using React and Webpack.

Because this is a Chrome extension, I can use manifest.json to load React and ReactDOM into the browser well before any line of my own code get executed. My understanding is that:

  • the react.js lib loaded by manifest.json show up as globals, accessible via window.React
  • webpack externals can be configured so that React and ReactDOM doesn't get bundled

Here are my files:

webpack.config.js

module.exports = {

  entry: './index.js',
  output: {
    filename: 'skinny-bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      }
    ]
  },

  externals: {
    react: {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      amd: 'react'
    },
    'react-dom': {
      root: 'reactDOM'
    }
  }
}

manifest.json

{
  "manifest_version": 2,
  "name": "Test Application",
  "version": "3.2",
  "description": "testing",
  "short_name": "some test",

  "author": "blah blah",

  "content_scripts": [
     {
       "matches": ["https://www.google.com/*"],
       "js": [
         "react.js",
         "react-dom.js",

         "skinny-bundle.js"
       ],
       "run_at": "document_idle"
     }
   ]
}

index.js

import HelloGreeting from './HelloGreeting'    

ReactDOM.render(
    <HelloGreeting />,
    document.getElementById('cst')
)

HelloGreeting.js

// import React from 'react'   <----- here is my problem!!!

// functional component test
const Hello = props => {
  return (
    <div>hello world</div>
  )
}

// class component test
class HelloGreeting extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <ul>
        <li><Hello /></li>
        <li>hello universe</li>
      </ul>
    )
  }
}

export default HelloGreeting

Here lies my problem. I have a simple React Component called HelloGreeting that doesn't work if I keep the import React from 'react' line. If I comment out the import, it actually works because my guess is that webpack just ignores it because React has been defined in webpack externals. If I leave the import statement in , I get a "Uncaught TypeError: Cannot read property 'Component' if undefined" error, possibly because Webpack tries to bundle and messing up with window.React somehow. I made this guess because of what webpack emits with or without the import.

If I comment out the import, webpack emits a smaller bundle:

Hash: 26f1526e2554c828c050
Version: webpack 3.5.5
Time: 80ms
           Asset     Size  Chunks             Chunk Names
skinny-bundle.js  5.75 kB       0  [emitted]  main
   [1] ./HelloGreeting.js 2.5 kB {0} [built]
    + 1 hidden module

If I keep my import, my webpack emits a larger bundle:

Hash: 1fc9353f1fe6dd935744
Version: webpack 3.5.5
Time: 77ms
           Asset     Size  Chunks             Chunk Names
skinny-bundle.js  6.05 kB       0  [emitted]  main
   [1] ./HelloGreeting.js 2.71 kB {0} [built]
    + 2 hidden modules

My question is, what can I do to configure webpack so that I still have my ES6 style imports and still have webpack NOT bundle react.js?

I really want to keep the import statement because these components will be used in future projects and I want to keep this as modular and portable as possible.

It turns out I was over-complicating webpack externals .

Changing from:

externals: {
    react: {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      amd: 'react'
    },
    'react-dom': {
      root: 'reactDOM'
    }
  }

to:

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

...solved my problem. Now webpack ignores all of my React code and keeps my bundle small.

https://github.com/webpack/webpack/issues/1275 helped me out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM