webpack dynamic import出错: SyntaxError: ‘import’ and ‘export’ may only appear at the top level

起因

今天尝试使用webpck的import()来做代码分割。

代码类似如下:

import('./nice-scroll').then(init => init(dom))

结果报错:

ERROR in ./js/utils/auto-set-height.js
Module build failed: SyntaxError: ‘import’ and ‘export’ may only appear at the top level (20:8)

分析

在package.json里面确认了一下,我用的webpack版本是^3.5.4,这个是一定支持import()方法的,那么问题应该就出在babel上了。

先截取我的babel-loader的部分配置:

use: {
    loader: 'babel-loader',
    options: {
        // 不采用.babelrc的配置
        "babelrc": false,
        "presets": [
            ["react"],
            ["es2015"]
        ],
        "plugins": [
            "transform-object-rest-spread",
            "transform-class-properties"
        ]
    }
}

一开始我的猜想是plugin es2015里面的transform-es2015-modules-commonjs先于webpack处理了代码,所以报错。

找了一下禁用的方法,改配置如下:

use: {
    loader: 'babel-loader',
    options: {
        // 不采用.babelrc的配置
        "babelrc": false,
        "presets": [
            ["react"],
            ["es2015", {module: false}]
        ],
        "plugins": [
            "transform-object-rest-spread",
            "transform-class-properties"
        ]
    }
}

还是不行。

后面一直各种关键词的搜索,偶然在github上面找到这个问题Dynamic `import()` crashing in `ModuleConcatenationPlugin`的一个回答:

Nope; babel will always process the code before webpack ever sees it; unless for some reason the file itself is being excluded from being processed by babel-loader.
This error is unrelated to babel; it’s a webpack issue.

这个回答,里面说到在webpack面对的代码都是babel处理过的,这个让我坚信问题还是在babel这块,继续搜索。

意外找到这个这篇文章:代码分离 – 使用import()。里面说到了一个插件:syntax-dynamic-import

Babel官方关于这个插件的描述是:

Syntax only
This plugin only allows Babel to parse this syntax. If you want to transform it then see dynamic-import-webpack or dynamic-import-node.

显然这是一个语法解析的插件,使得babel能够理解dynamic import的语法。再联系上面的报错信息里面的SyntaxError,结果有点明显了。

解决

npm install --save-dev babel-plugin-syntax-dynamic-import

然后调整babel-loader配置如下:

use: {
    loader: 'babel-loader',
    options: {
        // 不采用.babelrc的配置
        "babelrc": false,
        "presets": [
            ["react"],
            ["es2015", { "modules": false }]
        ],
        "plugins": [
            "syntax-dynamic-import",
            "transform-object-rest-spread",
            "transform-class-properties"
        ]
    }
}

重启webpack,顺利通过编译!!!

发表评论