是否可以将 "require" 和 "import" 与 Webpack 一起使用?

Is it possible to use both "require" and "import" together with Webpack?

我们必须更新一些依赖项才能切换到 Webpack 4,并且当尝试在同一项目中混合使用 importrequire 时,webpack 中出现警告,浏览器中出现错误。

我们有一个 非常 的大型项目(300 多个文件),其中一些文件使用 var Pkg = require('./fileName');module.exports = MyComponent,而其他文件使用 import Pkg from './fileName'export default MyComponent 并且宁愿不必使用 require/module.exports 遍历每一个并更新它们。

webpack警告:

WARNING in ./index.js 15:17-20
"export 'default' (imported as 'App') was not found in './App.jsx'

浏览器错误:

App.jsx:20 Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'
    at Module.eval (App.jsx:20)
    at eval (App.jsx:21)
    at Module../App.jsx (bootstrap:83)
    at __webpack_require__ (bootstrap:19)
    at eval (index.js:2)
    at Module../index.js (bootstrap:83)
    at __webpack_require__ (bootstrap:19)
    at bootstrap:83
    at bootstrap:83

package.json 依赖版本:

"@babel/cli": "^7.2.3",
"@babel/core": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.5",
"webpack": "^4.31.0",
"webpack-cli": "^3.3.2",

.babelrc

{
  "presets": [
    "@babel/preset-react",
    "@babel/preset-env"
  ]
}

.browserlistrc

{
  "browserslist": [
      ">0.25%",
      "ie 11",
      "not op_mini all"
  ]
}

webpack 配置:

rules: [
    {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [{
            loader: 'babel-loader',
            options: {
                babelrc: true
            }
        }],
    },
    // some other rules...   
]

index.js

import App from './App'

// Expose App to the window so we can utilize 
// it from within <script> tags
window.App = App

App.js

import React from 'react'
import ReactDOM from 'react-dom'

var App = (function () {
    return {
        route: function (route, properties) {
            return ReactDOM.render(
                <div>component markup</div>, document.getElementById('workspace')
            )
        }
    }
})()

// This works
// export default App

// This breaks
module.exports = App

index.html

<script>
    App.route('login', {some: 'props'});
</script>

从技术上讲,webpack 会打包(但会像您在那里看到的那样发出警告)。 但是,我们 webpack 团队建议您将代码库中使用的 CommonJS 语法的数量限制在尽可能小的范围内。

为什么?因为 CommonJS 在许多边缘情况下不可静态分析,因此 "bails out" 优化如 tree-shaking 和 scope-hoisting。这意味着您的 JavaScript(您网站上加载最昂贵的资源)将包含各种 dead/unused 代码。

在我们的 webpack documentation you can observe the listed optimization bailouts 中,您会注意到其中之一是代码中的 "using CommonJS" 或 "module" 符号。

从长远来看,这会对您的应用程序的网络性能产生重大负面影响!

如果迁移真的很痛苦,那么我会研究一个 codemod,它将 运行 跨越您的代码并将 require(如果可能)转换为导入!