动态import()使用webpack和babel语法错误

时间:2018-04-12 04:41:09

标签: javascript webpack babeljs babel-loader

我尝试使用动态导入将服务器生成的config.js文件插入到我们应用的生产版本中。

我试图以这种方式使用它:

import('./config').then(function(config){
    //create a global config variable
    config = config;
})

(暂时)

当我运行webpack时,我收到以下错误

Module build failed: SyntaxError: Unexpected token, expected { (1:6)

Research让我相信这与babel-loader有关,或许与动态导入效果不佳,但我认为已经解决了#34;有更新的版本。

解决方案似乎可能是安装Syntax Dynamic Importbabel-plugin-dynamic-import-node,但我不清楚哪一个或为什么。

package.json 的相关位:

{
  "name": "app",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "build": "node config/webpack/build.js",
  },
  "dependencies": {
    "amdi18n-loader": "^0.6.2",
    "async": "^2.6.0",
    "babel-core": "^6.26.0",
    "babel-eslint": "^8.2.2",
    "babel-loader": "^7.1.4",
    "babel-plugin-istanbul": "^4.1.6",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-stage-2": "^6.24.1",
    "babel-register": "^6.26.0",
    "chalk": "^2.3.0",
    "css-loader": "^0.28.10",
    "file-loader": "^1.1.6",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.0.1",
    "less-loader": "^4.0.6",
    "promise-polyfill": "^7.1.0",
    "raw-loader": "^0.5.1",
    "style-loader": "^0.20.2",
    "webpack": "^4.5.0"
  },
  "devDependencies": {
    "autoprefixer": "^7.2.3",
    "chromedriver": "^2.34.0",
    "copy-webpack-plugin": "^4.3.0",
    "cross-env": "^5.1.1",
    "cross-spawn": "^5.1.0",
    "eslint": "^4.13.1",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-loader": "^1.9.0",
    "eslint-plugin-html": "^4.0.1",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "inject-loader": "^3.0.1",
    "madge": "^2.0.0",
    "node-notifier": "^5.1.2",
    "optimize-css-assets-webpack-plugin": "^3.2.0",
    "ora": "^1.2.0",
    "portfinder": "^1.0.13",
    "postcss-import": "^11.0.0",
    "postcss-loader": "^2.0.9",
    "rimraf": "^2.6.2",
    "semver": "^5.4.1",
    "shelljs": "^0.7.8",
    "source-map-support": "*",
    "uglifyjs-webpack-plugin": "^1.1.4",
    "url-loader": "^0.6.2",
    "uuid": "^3.1.0",
    "webpack-bundle-analyzer": "^2.9.1",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.1.3",
    "webpack-merge": "^4.1.1"
  },
  "engines": {
    "node": ">= 4.0.0",
    "npm": ">= 3.0.0"
  }
}

我们将webpack.conf.js拆分为 webpack.base.conf

'use strict';
const path = require('path');
const utils = require('./utils');
const config = require('../');

function resolve(dir) {
    return path.join(__dirname, '../..', dir);
}

const createLintingRule = () => ({
    test: /\.(js|vue)$/,
    loader: 'eslint-loader',
    enforce: 'pre',
    include: [resolve('src'), resolve('test')],
    options: {
        formatter: require('eslint-friendly-formatter'),
        emitWarning: !config.dev.showEslintErrorsInOverlay
    }
});

module.exports = {
    context: path.resolve(__dirname, '../../'),
    entry: {
        app: './public/js/ide.js'
    },
    output: {
        path: config.build.assetsRoot,
        filename: '[name].js',
        publicPath: process.env.NODE_ENV === 'production'
            ? config.build.assetsPublicPath
            : config.dev.assetsPublicPath
    },
    optimization: {
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendor',
                    chunks: 'all'
                }
            }
        }
    },
    resolve: {
        extensions: ['.js', '.json', '.less'],
        alias: {
            '@': resolve('public/js'),
        },
        modules: ['less', 'node_modules']
    },
    module: {
        rules: [
            ...(config.dev.useEslint ? [createLintingRule()] : []),
            {
                test: /\.js$/,
                loader: 'babel-loader',
                include: [resolve('public/js'), resolve('test')],
                exclude: [
                    path.resolve(__dirname, "public/js/config.js")
                ],
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('img/[name].[hash:7].[ext]')
                }
            },
            {
                test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('media/[name].[hash:7].[ext]')
                }
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
                }
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.less$/,
                use: [{
                    loader: "style-loader" // creates style nodes from JS strings
                }, {
                    loader: "css-loader" // translates CSS into CommonJS
                }, {
                    loader: "less-loader" // compiles Less to CSS
                }]
            },
            {
                test: /\.hbs$/,
                use: ['raw-loader']
            }
        ]
    },
    node: {
        setImmediate: false,
        dgram: 'empty',
        fs: 'empty',
        net: 'empty',
        tls: 'empty',
        child_process: 'empty'
    }
};

...和 webpack.prod.conf.js

const webpackConfig = merge(baseWebpackConfig, {
    devtool: config.build.productionSourceMap ? config.build.devtool : false,
    output: {
        path: config.build.assetsRoot,
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': env
        }),
        new UglifyJsPlugin({
            uglifyOptions: {
                compress: {
                    warnings: false
                }
            },
            sourceMap: config.build.productionSourceMap,
            parallel: true
        }),
        new OptimizeCSSPlugin({
            cssProcessorOptions: config.build.productionSourceMap
                ? { safe: true, map: { inline: false } }
                : { safe: true }
        }),
        new HtmlWebpackPlugin({
            filename: process.env.NODE_ENV === 'testing'
                ? 'public/html/ide.html'
                : config.build.index,
            template: 'public/html/ide.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
            },
            chunksSortMode: 'dependency'
        }),
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        }),
        new webpack.HashedModuleIdsPlugin(),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new CopyWebpackPlugin([
            {
                from: path.resolve(__dirname, '../../public/fonts'),
                to: config.build.assetsFonts,
            },
            {
                from: path.resolve(__dirname, '../../public/img'),
                to: config.build.assetsImg,
            }
        ])
    ]
});

1中,用户表示babel-loader应该"只是工作"现在有动态导入,所以我不确定我错过了什么。有什么过时的吗?我的配置有些奇怪吗?

1 个答案:

答案 0 :(得分:4)

您需要做几件事。

首先,与上述评论中的某些人一样,您需要为配置使用不同的变量名称。此外,如果您以这种方式使用import,则您获得的对象是ES6导出的对象,因此您的数据将位于default

import('./config').then(function(localConfig){
    //create a global config variable
    config = localConfig.default;
})

接下来,您获得的错误是babel未使用正确预设的结果。你需要至少在第二阶段才能发挥作用。

{
    test: /\.js$/,
    loader: 'babel-loader',
    options: {
        presets: ['es2015','stage-2']
    }
    include: [resolve('public/js'), resolve('test')],
    exclude: [
        path.resolve(__dirname, "public/js/config.js")
    ],
},

这将解决您的错误,但仍然不是您想要的。现在发生的一切是webpack将你的配置文件拆分成它自己的块,在运行时发出一个新的http请求来获取这个文件。但它不会使用服务器上的配置文件,而是使用构建中生成的块 要在运行时加载服务器上的实际配置,您需要在应用程序中发出正常的http请求 这是一个很好的stackoverflow答案。
https://stackoverflow.com/a/36725115/9083959