最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Unexpected character '@' for webpack "externals" option - Stack Overflow

programmeradmin4浏览0评论

I've found a lot of stuff about "Unexpected character '@'" happening with webpack, but none of it related specifically to, or helpful with, getting that error for the externals webpack option. I've used this before, both with and without @-signs, without any trouble, so I don't know why webpack is getting cranky now.

const TerserPlugin = require('terser-webpack-plugin');

module.exports = () => {
  return {
    mode: 'production',
    target: 'node',
    entry: './build.ts',
    output: {
      path: __dirname,
      filename: `build.js`
    },
    node: {
      __dirname: false,
      __filename: false,
    },
    resolve: {
      extensions: ['.ts', '.js'],
      mainFields: ['es2015', 'module', 'main', 'browser']
    },
    module: {
      rules: [
        {
          test: /\.ts$/i,
          loader: 'ts-loader',
          options: { configFile: 'tsconfig-build.json' },
          exclude: [/\/node_modules\//]
        }
      ]
    },
    externals: ['chalk', '@tubular/util'],
    optimization: {
      minimize: true,
      minimizer: [new TerserPlugin({
        terserOptions: {
          mangle: false,
          output: { max_line_len: 511 }
        }
      })],
    },
  };
};

The @ is a necessary part of the package name that I want to exclude, and I've exclude such packages before, so this is both mysterious and annoying.

Anyone have any idea what's wrong here?

I've found a lot of stuff about "Unexpected character '@'" happening with webpack, but none of it related specifically to, or helpful with, getting that error for the externals webpack option. I've used this before, both with and without @-signs, without any trouble, so I don't know why webpack is getting cranky now.

const TerserPlugin = require('terser-webpack-plugin');

module.exports = () => {
  return {
    mode: 'production',
    target: 'node',
    entry: './build.ts',
    output: {
      path: __dirname,
      filename: `build.js`
    },
    node: {
      __dirname: false,
      __filename: false,
    },
    resolve: {
      extensions: ['.ts', '.js'],
      mainFields: ['es2015', 'module', 'main', 'browser']
    },
    module: {
      rules: [
        {
          test: /\.ts$/i,
          loader: 'ts-loader',
          options: { configFile: 'tsconfig-build.json' },
          exclude: [/\/node_modules\//]
        }
      ]
    },
    externals: ['chalk', '@tubular/util'],
    optimization: {
      minimize: true,
      minimizer: [new TerserPlugin({
        terserOptions: {
          mangle: false,
          output: { max_line_len: 511 }
        }
      })],
    },
  };
};

The @ is a necessary part of the package name that I want to exclude, and I've exclude such packages before, so this is both mysterious and annoying.

Anyone have any idea what's wrong here?

Share Improve this question asked May 15, 2021 at 19:30 kshetlinekshetline 13.8k6 gold badges49 silver badges91 bronze badges 5
  • I'm facing the same problem with '@vue/position-api'. Did you filled a bug report or something ? – Johnny5 Commented May 20, 2021 at 14:06
  • No, I haven't filed a bug report. I wasn't sure if it was a bug, or something I'd set up incorrectly. It's beginning to sound like a bug, however. What's weird is I have other projects right now that use the @ without any problem, so I don't know what the difference is well enough to characterize the bug. – kshetline Commented May 20, 2021 at 14:13
  • Does your working projects uses the same version of webpack ? Mine uses webpack 5.37.0 – Johnny5 Commented May 20, 2021 at 14:41
  • The error does not happend if I add type: 'umd' to the library node. – Johnny5 Commented May 20, 2021 at 18:17
  • I'm using webpack 5.37.0 both where @ works and where it doesn't. But just like you, where it works I'm using 'umd'. – kshetline Commented May 20, 2021 at 18:58
Add a ment  | 

3 Answers 3

Reset to default 4

I found a solution, I was also facing the same issue with Vue.js Project --mode production. All other modes were working fine.

externals:[
      {
        ["@pany/library-name"]:{
          root: "@pany/library-name"
        }
      }
    ]

This is basically using the object syntax from official docs.

Webpack externals option is dependent on the externalsType one. By default, externalsType is var, this means that you expect this variable to exists in the global scope.

For example, if we import jQuery in the browser through a script link:

<script src="https://code.jquery./jquery-3.7.0.slim.min.js" ...></script>

There will be a global variable in the window object named jQuery, so this Webpack configuration:

externals: {
  jquery: 'jQuery'
}

Is stating:

When you find an import from jquery remove it from the bundle and use the jQuery global variable in its place.

If you put this configuration without externalsType:

externals: ['@tubular/util'],

Webpack will try to replace those requires or imports by a global variable named @tubular/util in this way:

var t=@tubular/util;

And that will throw an error for sure.

On your specific case, @tubular/util imported through a script tag creates a tbUtil global variable, so your configuration should be:

externals: {
    '@tubular/util': 'tbUtil'  
}

This error could also appear if someone is trying to pile a Node bundle and they want to exclude some packages from the bundle that are already installed. For example, if you use this externals configuration without specifying a proper externalsType, you will get a similar error.

{
    externals: ['@babel/core']
}

In these cases, you should specify a proper externalsType depending on your needs (these are all the options):

{
    externals: ['@babel/core'],
    externalsType: 'monjs'
}

And then, Webpack will replace

import { transform } from '@babel/core';

into something like:

var b=require("@babel/core");
var t=b.transform;

And it will not ship @babel/core in the bundle.

I found an answer, but it's certainly not the answer I was looking for.

If I use the package webpack-node-externals, I can externalize all node_modules like this:

const nodeExternals = require('webpack-node-externals');

 // ...

    externalsPresets: { node: true },
    externals: [nodeExternals()],

In this particular case excluding all node externals happens to be just fine, so webpack-node-externals solves my immediate problem. But if I wanted to be more selective, and wanted to exclude a package with an @ in the name, I'd still have a mystery on my hands.

发布评论

评论列表(0)

  1. 暂无评论