odoe / jsapi-webpack

Sample using the webpack plugin with babel
20 stars 10 forks source link

Why is 'externals' needed in webpack.config.js? #14

Open 46319943 opened 3 years ago

46319943 commented 3 years ago

When I use ES6 for development, I ran into this problem: https://github.com/Esri/arcgis-webpack-plugin/issues/11#issue-324173559

By setting externals in webpack.config.js, I successfully solved the problem.

externals: [
    (context, request, callback) => {
      if (/pe-wasm$/.test(request)) {
        return callback(null, "amd " + request);
      }
      callback();
    }
  ],

I know that the purpose of this code is to introduce external modules in the form of AMD modules at runtime. But why do we need to set this item? In the official example, there is no externals setting in the configuration file. How is this going?

Even if I don't use babel and don't set externals, there will be problems. In the official vue example, it uses babel to compile the ts file without setting externals and no errors.

This is the official webpack configuration file for using babel in vue: https://github.com/Esri/arcgis-js-cli/blob/master/templates/vue/app/webpack.config.js

odoe commented 3 years ago

This was from an old version of the plugin and api. It shouldn't be needed anymore.

The externals was used so that webpack doesn't try to parse those files. The wasm stuff is already compiled and shouldn't be processed any further. Now we use the node globals to prevent webpack build errors for wasm files.

46319943 commented 3 years ago

Thank you, I seem to have understood the externals in the configuration file. However, even though I have configured node global, deleting externals will still make my code report errors.

My webpack configuration file is as follows:

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

const ArcGISPlugin = require("@arcgis/webpack-plugin");

module.exports = {
  mode: 'development',
  devtool: 'source-map',
  devServer: {
    compress: true,
    host: '0.0.0.0',
    disableHostCheck: true,
    contentBase: './dist',
    writeToDisk: true,
    hot: true,
  },
  entry: {
    app: './src/app.js',
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist/bundle'),
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
  resolve: {
    alias: {
      vue: 'vue/dist/vue.js',
      '~': path.resolve('src'),
      '@': path.resolve('src/components'),
      'MapUtil': path.resolve('src/map_utils.js'),
      'NewsUtil': path.resolve('src/news_utils.js'),
      'CommonUtil': path.resolve('src/common_utils.js'),
    }
  },
  module: {
    rules: [{
      test: /\.vue$/,
      loader: 'vue-loader',
    },
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      loader: 'babel-loader',
      options: {
        cacheDirectory: true,
      }
    },
    {
      test: /\.css$/,
      use: [
        'vue-style-loader',
        'css-loader',
      ]
    },
    {
      test: /\.scss$/,
      use: [
        'vue-style-loader',
        'css-loader',
        'sass-loader'
      ]
    },
    {
      test: /\.(eot|svg|ttf|woff|woff2)$/,
      loader: 'file-loader'
    },
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new CleanWebpackPlugin(),
    new BundleAnalyzerPlugin({ analyzerPort: 8919 }),

    new ArcGISPlugin()
  ],
  externals: [
    {
      Loca: 'Loca',
      AMap: 'AMap'
    },
    // (context, request, callback) => {
    //   if (/pe-wasm$/.test(request)) {
    //     return callback(null, "amd " + request);
    //   }
    //   else if (/i3s$/.test(request)) {
    //     return callback(null, 'amd ' + request);
    //   }
    //   callback();
    // }
  ],
  node: {
    process: false,
    global: false,
    fs: 'empty',
  },

};

When I commented out the externals configuration item in the configuration file, an error occurred in webpack packaging:

ERROR in ./node_modules/arcgis-js-api/geometry/support/pe-wasm.wasm
Module not found: Error: Can't resolve 'a' in 'D:\Document\新闻地图\NewsClientJS\node_modules\arcgis-js-api\geometry\support'
 @ ./node_modules/arcgis-js-api/geometry/support/pe-wasm.wasm
 @ ./node_modules/arcgis-js-api/geometry/pe.js
 @ ./node_modules/arcgis-js-api/geometry/projection.js
 @ ./node_modules/arcgis-js-api/layers/graphics/data/projectionSupport.js
 @ ./node_modules/arcgis-js-api/views/2d/layers/graphics/GraphicsView2D.js
 @ ./node_modules/arcgis-js-api/views/2d/mapViewDeps.js
 @ ./node_modules/arcgis-js-api/views/MapView.js
 @ ./node_modules/babel-loader/lib??ref--1!./node_modules/vue-loader/lib??vue-loader-options!./src/components/TheArcGISDemo.vue?vue&type=script&lang=js&
 @ ./src/components/TheArcGISDemo.vue?vue&type=script&lang=js&
 @ ./src/components/TheArcGISDemo.vue
 @ ./src/router.js
 @ ./src/app.js

ERROR in ./node_modules/arcgis-js-api/libs/i3s/i3s.wasm
Module not found: Error: Can't resolve 'env' in 'D:\Document\新闻地图\NewsClientJS\node_modules\arcgis-js-api\libs\i3s'
 @ ./node_modules/arcgis-js-api/libs/i3s/i3s.wasm
 @ ./node_modules/arcgis-js-api/libs/i3s/I3SWorker.js
 @ ./node_modules/arcgis-js-api/views/3d/layers/SceneLayerWorker.js
 @ ./node_modules/arcgis-js-api/core/workers/registry.js
 @ ./node_modules/arcgis-js-api/core/workers/RemoteClient.js
 @ ./node_modules/arcgis-js-api/core/workers/workers.js
 @ ./node_modules/arcgis-js-api/core/workers.js
 @ ./node_modules/arcgis-js-api/views/MapView.js
 @ ./node_modules/babel-loader/lib??ref--1!./node_modules/vue-loader/lib??vue-loader-options!./src/components/TheArcGISDemo.vue?vue&type=script&lang=js&
 @ ./src/components/TheArcGISDemo.vue?vue&type=script&lang=js&
 @ ./src/components/TheArcGISDemo.vue
 @ ./src/router.js
 @ ./src/app.js

ERROR in ./node_modules/arcgis-js-api/libs/i3s/i3s.wasm
Module not found: Error: Can't resolve 'wasi_snapshot_preview1' in 'D:\Document\新闻地图\NewsClientJS\node_modules\arcgis-js-api\libs\i3s'
 @ ./node_modules/arcgis-js-api/libs/i3s/i3s.wasm
 @ ./node_modules/arcgis-js-api/libs/i3s/I3SWorker.js
 @ ./node_modules/arcgis-js-api/views/3d/layers/SceneLayerWorker.js
 @ ./node_modules/arcgis-js-api/core/workers/registry.js
 @ ./node_modules/arcgis-js-api/core/workers/RemoteClient.js
 @ ./node_modules/arcgis-js-api/core/workers/workers.js
 @ ./node_modules/arcgis-js-api/core/workers.js
 @ ./node_modules/arcgis-js-api/views/MapView.js
 @ ./node_modules/babel-loader/lib??ref--1!./node_modules/vue-loader/lib??vue-loader-options!./src/components/TheArcGISDemo.vue?vue&type=script&lang=js&
 @ ./src/components/TheArcGISDemo.vue?vue&type=script&lang=js&
 @ ./src/components/TheArcGISDemo.vue
 @ ./src/router.js
 @ ./src/app.js
 「wdm」: Failed to compile.

I have to configure externals in webpack to make the packaging process work properly. This is my package.json file:

{
  "name": "newsclientjs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "pro": "webpack-dev-server --hot --mode=production",
    "build": "webpack",
    "start": "webpack-dev-server --hot"
  },
  "browser": {
    "fs": false,
    "path": false,
    "os": false
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@deck.gl/mapbox": "^8.1.9",
    "@mapbox/mapbox-gl-draw": "^1.1.2",
    "@tinymce/tinymce-vue": "^3.2.1",
    "@turf/turf": "^5.1.6",
    "animate.css": "^3.7.2",
    "axios": "^0.19.2",
    "clipboard": "^2.0.6",
    "deck.gl": "^8.1.9",
    "echarts": "^4.7.0",
    "echarts-wordcloud": "^1.1.3",
    "element-ui": "^2.13.1",
    "gcoord": "^0.2.3",
    "geojson": "^0.5.0",
    "intro.js": "^2.9.3",
    "jsoneditor": "^9.0.3",
    "mapbox-gl": "^1.9.1",
    "mavon-editor": "^2.9.0",
    "normalize.css": "^8.0.1",
    "qrcode.vue": "^1.7.0",
    "shepherd.js": "^8.0.2",
    "view-design": "^4.2.0",
    "vue": "^2.6.11",
    "vue-amap": "^0.5.10",
    "vue-awesome": "^4.0.2",
    "vue-clipboard2": "^0.3.1",
    "vue-echarts": "^5.0.0-beta.0",
    "vue-router": "^3.1.6",
    "vue-video-player": "^5.0.2",
    "vuedraggable": "^2.23.2",
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@amap/amap-jsapi-loader": "0.0.1",
    "@arcgis/webpack-plugin": "^4.16.3",
    "@babel/core": "^7.10.3",
    "@babel/preset-env": "^7.10.3",
    "@types/mapbox-gl": "^1.10.2",
    "babel-loader": "^8.1.0",
    "babel-plugin-component": "^1.1.1",
    "babel-plugin-import": "^1.13.0",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.5.2",
    "eslint": "^6.8.0",
    "eslint-plugin-vue": "^7.0.0-alpha.1",
    "file-loader": "^6.0.0",
    "node-sass": "^4.14.1",
    "sass-loader": "^8.0.2",
    "typescript": "^2.9.2",
    "vue-loader": "^15.9.1",
    "vue-template-compiler": "^2.6.11",
    "webpack": "^4.43.0",
    "webpack-bundle-analyzer": "^3.8.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "webpack-node-externals": "^1.7.2"
  }
}

This is really weird. I modified the configuration file for a whole day, but I didn’t figure out where the problem was.😥