vue cli3 整合Cesium,處理build 時內存溢出問題

一直使用cesium,但是都是使用script直接引入的,但是在將其放置在增加路由的子頁面中中時會出現一個問題,刷新後提示cesium is undefined
看直接引入cesium.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <link rel="stylesheet" href="libs/Cesium/Widgets/widgets.css">
    <link rel="stylesheet" href="//at.alicdn.com/t/font_1668594_l9pybqe35u.css">
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="screen"></div>
<!-- built files will be auto injected -->
<script type="text/javascript" src="libs/Cesium/Cesium.js"></script>
</body>
</html>

沒刷新之前


刷新後提示錯誤


刷新後

。。。。。。。。

後來決定根據cesium官網來改進配置

一、安裝ceium

  npm install --save-dev cesium

二、配置vue.config.js

1、在vue.config.js增加cesium目錄映射

// The path to the CesiumJS source code
const cesiumSource = 'node_modules/cesium/Source';
const cesiumWorkers = '../Build/Cesium/Workers';

2、配置別名

    chainWebpack: config => {
        config.resolve.alias
            .set("cesium", resolve(cesiumSource))
    },

3、使用WebpackPlugin拷貝cesium資源到dist

    configureWebpack: config => {
        const plugins = [];
        plugins.push(
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, cesiumWorkers), to: 'Workers' } ])
        );
        plugins.push(
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Assets'), to: 'Assets' } ])
        );
        plugins.push(
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Widgets'), to: 'Widgets' } ])
        );
        plugins.push(
            new webpack.DefinePlugin({ CESIUM_BASE_URL: JSON.stringify('./') })
        );

        config.plugins = [...config.plugins, ...plugins];
    },

4、main.js引用

main.js引用

將Home.vue修改用於測試
Home.vue頁面

最後vue.config.js配置是這樣的

const path = require("path");
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin')
// The path to the CesiumJS source code
const cesiumSource = 'node_modules/cesium/Source';
const cesiumWorkers = '../Build/Cesium/Workers';
function resolve(dir) {
    return path.join(__dirname, dir)
}

module.exports = {
    
    publicPath: process.env.NODE_ENV === 'production'
        ? './'
        : '/',
    devServer: {
        port: 8099,
        disableHostCheck: true,
    },
    chainWebpack: config => {
        config.resolve.alias
            .set("cesium", resolve(cesiumSource))
    },
    configureWebpack: config => {
        const plugins = [];
        plugins.push(
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, cesiumWorkers), to: 'Workers' } ])
        );
        plugins.push(
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Assets'), to: 'Assets' } ])
        );
        plugins.push(
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Widgets'), to: 'Widgets' } ])
        );
        plugins.push(
            new webpack.DefinePlugin({ CESIUM_BASE_URL: JSON.stringify('./') })
        );

        config.plugins = [...config.plugins, ...plugins];
    },
}

5、 運行測試


npm run serve

提示了幾個錯誤

 WARNING  Compiled with 3 warnings                                                                              09:14:40

 warning  in ./src/main.js

"export 'default' (imported as 'Cesium') was not found in 'cesium/Cesium'

 warning  in ./node_modules/cesium/Source/Core/buildModuleUrl.js

Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

 warning  in ./node_modules/cesium/Source/Core/buildModuleUrl.js

Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

看第一個錯誤相信熟悉過node 或者commonJS都知道其實,Cesium.js沒有 export default默認導出

三、錯誤處理

那麼就將

import  Cesium from 'cesium/Cesium'

修改爲

//  const Cesium  = require('cesium/Cesium') ; // 也可以改成require引入
import * as Cesium from 'cesium/Cesium'

好了目前只有兩個錯誤了
控制檯

看地圖也加載出來了
預覽
但是還是有兩個【錯誤】…

看到有朋友說要增加unknownContextCritical配置,如:
配置unknownContextCritical

於是我試着這樣去修改配置

    chainWebpack: config => {
        config.module
            .unknownContextCritical(false)
            .end()
        config.resolve.alias
            .set("cesium", resolve(cesiumSource))
    },

但是運行是報錯的


ERROR  TypeError: config.module.unknownContextCritical is not a function

看了半天vue 配置文檔,最後將回調函數換成對象就OK了

這裏就不囉嗦了,直接看最終的vue.config.js配置吧

const path = require("path");
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin')
// The path to the CesiumJS source code
const cesiumSource = 'node_modules/cesium/Source';
const cesiumWorkers = '../Build/Cesium/Workers';
function resolve(dir) {
    return path.join(__dirname, dir)
}

module.exports = {

    publicPath: process.env.NODE_ENV === 'production'
        ? './'
        : '/',
    devServer: {
        port: 8099,
        disableHostCheck: true,
    },
    configureWebpack: {
        output: {
            sourcePrefix: ' '
        },
        amd: {
            toUrlUndefined: true
        },
        resolve: {
            alias: {
                'vue$': 'vue/dist/vue.esm.js',
                '@': path.resolve('src'),
                'cesium': path.resolve(__dirname, cesiumSource)
            }
        },
        plugins: [
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, cesiumWorkers), to: 'Workers'}]),
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Assets'), to: 'Assets'}]),
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Widgets'), to: 'Widgets'}]),
            new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'ThirdParty/Workers'), to: 'ThirdParty/Workers'}]),
            new webpack.DefinePlugin({
                CESIUM_BASE_URL: JSON.stringify('./')
            })
        ],
        module: {
            unknownContextCritical: /^.\/.*$/,
            unknownContextCritical: false

        }
    }
}

控制檯

四、deal with ‘JavaScript heap out of memory’ in vue build


> [email protected] build D:\YLKJPro\tf-pipe-gallery
> vue-cli-service build


\  Building for production...
<--- Last few GCs --->

[10780:000001C5544A9790]   232452 ms: Mark-sweep 1383.4 (1420.6) -> 1383.0 (1420.6) MB, 1387.6 / 0.0 ms  (average mu = 0.105, current mu = 0.017) allocation failure scavenge might not succeed
[10780:000001C5544A9790]   233690 ms: Mark-sweep 1383.7 (1420.6) -> 1383.3 (1421.1) MB, 1234.4 / 0.0 ms  (average mu = 0.057, current mu = 0.003) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0000026F403D0461]
Security context: 0x01f699a9d971 <JSObject>
    1: /* anonymous */(aka /* anonymous */) [000002EFA8A9A541] [D:\YLKJPro\tf-pipe-gallery\node_modules\webpack-sources\lib\applySourceMap.js:~58] [pc=0000026F4126674D](this=0x03d26f9825b1 <undefined>,0x02080a98c961 <String[6]: Array(>,0x01b0a61506b9 <Object map = 000000E391A70FC1>)
    2: SourceNode_walk [0000036225A356F9] [D:\YLKJPro\tf-pipe-gallery\node...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

Writing Node.js report to file: report.20200402.161224.10780.001.json
Node.js report completed
 1: 00007FF6B7CCCC3A public: __cdecl v8::internal::GCIdleTimeHandler::GCIdleTimeHandler(void) __ptr64+4618
 2: 00007FF6B7C798B6 uv_loop_fork+80934
 3: 00007FF6B7C7A411 uv_loop_fork+83841
 4: 00007FF6B8070F1E void __cdecl v8::internal::FatalProcessOutOfMemory(class v8::internal::Isolate * __ptr64,char const * __ptr64)+798
 5: 00007FF6B8070E57 void __cdecl v8::internal::FatalProcessOutOfMemory(class v8::internal::Isolate * __ptr64,char const * __ptr64)+599
 6: 00007FF6B8120E74 public: static bool __cdecl v8::internal::Heap::RootIsImmortalImmovable(int)+14900
 7: 00007FF6B8116994 public: bool __cdecl v8::internal::Heap::CollectGarbage(enum v8::internal::AllocationSpace,enum v8::internal::GarbageCollectionReason,enum v8::GCCallbackFlags) __ptr64+7556
 8: 00007FF6B8115068 public: bool __cdecl v8::internal::Heap::CollectGarbage(enum v8::internal::AllocationSpace,enum v8::internal::GarbageCollectionReason,enum v8::GCCallbackFlags) __ptr64+1112
 9: 00007FF6B811EAB7 public: static bool __cdecl v8::internal::Heap::RootIsImmortalImmovable(int)+5751
10: 00007FF6B811EB36 public: static bool __cdecl v8::internal::Heap::RootIsImmortalImmovable(int)+5878
11: 00007FF6B82A78E1 public: class v8::internal::Handle<class v8::internal::HeapObject> __cdecl v8::internal::Factory::NewFillerObject(int,bool,enum v8::internal::AllocationSpace) __ptr64+49
12: 00007FF6B8360CEA public: static int __cdecl v8::internal::StoreBuffer::StoreBufferOverflow(class v8::internal::Isolate * __ptr64)+27082
13: 0000026F403D0461

看到這一片錯誤的確叫人頭疼。。。

最後在vue 官網Issues終於找到了解決方法

直接修改package.json中的script


    "build": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js build --open"

再次npm run build 看見buil 成功了

build success

ok到此總算完美解決了所有問題。

感謝閱讀,希望對於剛入門的cesium 開發者一些幫助,謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章