11

I wanted to upgrade the version of Monaco Editor to v0.31.1. I did npm install monaco-editor@0.31.1, and the recompilation by sudo PORT=8000 HTTPS=true ./node_modules/.bin/react-app-rewired start gave me the following error:

Failed to compile.

./node_modules/monaco-editor/esm/vs/language/html/monaco.contribution.js 154:11
Module parse failed: Unexpected token (154:11)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|     dispose() {
|       onLanguageListener.dispose();
>       mode?.dispose();
|       mode = void 0;
|     }

Could anyone help?

Edit 1: package.json before the upgrading:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@fluentui/react": "^8.33.0",
    "@handsontable/react": "^9.0.2",
    "@material-ui/core": "^4.9.8",
    "@microsoft/office-js-helpers": "^1.0.2",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@types/react-stripe-elements": "^6.0.4",
    "@uifabric/react-cards": "^0.109.49",
    "axios": "^0.19.2",
    "color": "^3.1.2",
    "copy-to-clipboard": "^3.3.1",
    "cross-storage": "^1.0.0",
    "dva": "^2.4.1",
    "dva-model-creator": "^0.4.3",
    "formik": "^2.1.4",
    "handsontable": "^9.0.2",
    "highcharts": "^7.0.3",
    "highcharts-react-official": "^3.0.0",
    "lodash": "^4.17.15",
    "moment": "^2.24.0",
    "monaco-editor": "^0.20.0",
    "monaco-languageclient": "^0.13.0",
    "node-sass": "^4.14.1",
    "office-ui-fabric-core": "^11.0.0",
    "office-ui-fabric-react": "^7.105.4",
    "query-string": "^6.11.1",
    "react": "^16.13.1",
    "react-app-polyfill": "^1.0.6",
    "react-bootstrap": "^1.0.1",
    "react-dom": "^16.13.1",
    "react-meta-tags": "^1.0.1",
    "react-monaco-editor": "^0.35.0",
    "react-scripts": "3.4.1",
    "react-stripe-elements": "^6.1.1",
    "redux-devtools-extension": "^2.13.8",
    "styled-components": "^5.0.1",
    "typescript": "^3.8.3",
    "yup": "^0.28.3"
  },
  "scripts": {
    "start": "PORT=3000 react-app-rewired start",
    "start:https": "HTTPS=true  react-app-rewired start",
    "build": "react-scripts --max_old_space_size=8096 build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@types/color": "^3.0.1",
    "@types/cross-storage": "^0.8.29",
    "@types/jest": "^25.1.4",
    "@types/lodash": "^4.14.149",
    "@types/node": "^13.9.5",
    "@types/office-js": "^1.0.92",
    "@types/query-string": "^6.3.0",
    "@types/react": "^16.9.27",
    "@types/react-dom": "^16.9.5",
    "@types/react-redux": "^7.1.7",
    "@types/styled-components": "^5.0.1",
    "@types/yup": "^0.26.33",
    "css-loader": "^3.5.3",
    "react-app-rewired": "^2.1.8",
    "style-loader": "^1.2.1"
  }
}

When "monaco-editor": "^0.20.0", npm list monaco-editor returns

$ npm list monaco-editor
npm list monaco-editor
frontend@0.1.0 /frontend
├── UNMET DEPENDENCY monaco-editor@0.20.0 
└─┬ UNMET DEPENDENCY react-monaco-editor@0.35.0
  └── UNMET DEPENDENCY monaco-editor@0.20.0 

npm ERR! missing: monaco-editor@0.20.0, required by frontend@0.1.0
npm ERR! missing: react-monaco-editor@0.35.0, required by frontend@0.1.0
npm ERR! missing: monaco-editor@0.20.0, required by react-monaco-editor@0.35.0

When "monaco-editor": "^0.31.1", npm list monaco-editor returns

$ npm list monaco-editor
frontend@0.1.0 /frontend
├── UNMET DEPENDENCY monaco-editor@0.31.1 
└─┬ UNMET DEPENDENCY react-monaco-editor@0.35.0
  └── UNMET DEPENDENCY monaco-editor@0.31.1 

npm ERR! missing: monaco-editor@0.31.1, required by frontend@0.1.0
npm ERR! missing: react-monaco-editor@0.35.0, required by frontend@0.1.0
npm ERR! missing: monaco-editor@0.31.1, required by react-monaco-editor@0.35.0

Edit 2:

Following the anwser of @Bart, I installed @babel/preset-env by yarn add @babel/preset-env --dev and created babel.config.json with {"presets": ["@babel/preset-env"]}, but react-app-rewired start gave the same error.

Then, I realized that I do have a file config-overrides.js, the content is as follows:

module.exports = function override (config, env) { 
    // disable chunks so the index.html won't change during development 
    config.optimization.splitChunks = {
        cacheGroups: {
            default: false,
        },
    };
    config.optimization.runtimeChunk = false;
    return config;
}

I then added the part for config.module.rules, but the compilation returned the same error.

Additionally, it seems that the project can be built with yarn build without this error. But building the project takes time.

module.exports = function override (config, env) {
    config.module.rules = 
        [
          {
            test: /\.m?js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
    
    // disable chunks so the index.html won't change during development 
    config.optimization.splitChunks = {
        cacheGroups: {
            default: false,
        },
    };
    config.optimization.runtimeChunk = false;
    return config;
}
SoftTimur
  • 5,630
  • 38
  • 140
  • 292

4 Answers4

11

The problem seems to be with the optional chaining syntax (the ?. in mode?.dispose();). This is also listed as a breaking change in the changelog of Monaco:

the generated code is now bundled with ESBuild and the generated code makes use of newer browser features, e.g. optional chaining. These features should be available in all browsers, but they might not be parsed correctly by older JS parsers, specifically parcel v1 might have problems parsing the JS.

This syntax can be handled well by the correct Babel plugin. In general, it’s better to use @babel/preset-env instead of separate plugins. This preset takes care of several plugins at once. Do you have a babel config file where you could include this preset? This can be as simple as installing @babel/preset-env as a dev dependency, and creating a babel.config.json file in your project root with the following contents:

{
  "presets": ["@babel/preset-env"]
}

Secondly, it could mean that your Babel config is already working correctly, but that anything inside node_modules is ignored by Webpack (used under the hood by Create React App), as is often done to speed up transpilation times. Then you’ll have to find a way to overrule the Webpack config so that your monaco dependency is not skipped for transpilation.

I see you’re already using react-app-rewired, so updating the Webpack config is done as explained in their documentation:

// config-overrides.js
module.exports = function override (config, env) { 
    // disable chunks so the index.html won't change during development 
    config.optimization.splitChunks = {
        cacheGroups: {
            default: false,
        },
    };
    config.optimization.runtimeChunk = false;
    
    config.module.rules = [
      {
        test: /node_modules\/monaco-editor/,
        use: {
          loader: 'babel-loader',
          // if you include your babel config here,
          // you don’t need the `babel.config.json` file
          options: { presets: ['@babel/preset-env'] }
        }
      },
      ...config.module.rules
    ]
    return config;
}

Integrating Babel can be done via babel-loader, see instructions here.

agilgur5
  • 667
  • 12
  • 30
Bart
  • 1,600
  • 1
  • 13
  • 29
  • Thank you... I installed `@babel/preset-env` by `yarn add @babel/preset-env --dev` and created a `babel.config.json` with your content, but the compilation gave the same error. For your second point, I don't know what to do... – SoftTimur Jan 10 '22 at 13:11
  • Added some more pointers for your help – Bart Jan 11 '22 at 16:30
  • Thank you. I added `Edit 2` to OP. Could you help? – SoftTimur Jan 12 '22 at 09:53
  • Are you sure the part you added for `config.module.rules` is correct? The webpack documentation that I linked provides an example where `node_modules` is excluded, as is most common. But here we’re trying to do the opposite. I updated my answer with an example `config-overrides.js` (maybe the `test` regex is not perfect, but you get the idea) – Bart Jan 13 '22 at 22:10
  • I'm not sure, i was wondering that too. Could you propose a precise modification? – SoftTimur Jan 13 '22 at 22:12
  • I commented `exclude: /(node_modules|bower_components)/,` in my code, i still had the same error. – SoftTimur Jan 13 '22 at 22:17
  • It could be that another loader (see `...config.module?.rules` above) doesn’t understand the `?.` syntax. I updated the order of the rules in my example above — `babel-loader` should go first. – Bart Jan 13 '22 at 22:20
  • 1
    Thank you for this... But could you work directly on my `config-overrides.js`? My knowledge of webpack and react-app-rewired does not allow me to adapt your answer to my code. – SoftTimur Jan 13 '22 at 22:21
  • I see your update, I run it, still the same error. But I just realized that, no matter what wrong text I put in `config-overrides.js`, we still first see `mode?.dispose();` error. It seems that `config-overrides.js` did not play its role. – SoftTimur Jan 13 '22 at 22:37
  • Is the file in your repository root? You can double-check if it’s used at all by placing a `console.log` or `throw new Error()` somewhere in the file – Bart Jan 13 '22 at 23:48
  • I realized that `sudo PORT=8000 HTTPS=true ./node_modules/.bin/react-scripts start` ignored `config-overrides.js`. I should use `sudo PORT=8000 HTTPS=true ./node_modules/.bin/react-app-rewired start`. But with your `config-overfides.js` I had the same error. – SoftTimur Jan 14 '22 at 12:13
  • The `build` command seems to work, and is run via `react-scripts`. Would it be an option to run `start` via `react-scripts` as well? – Bart Jan 14 '22 at 19:56
  • Did this help fix your issue? – Bart Jan 20 '22 at 10:21
  • 1
    Hello, you did help, but I could not make this answer work. At the moment, I used the workaround described in my answer. I will not select your answer, but I will give you the bounty for the help. – SoftTimur Jan 20 '22 at 10:23
  • I solved this issue by installing a specific version of the *monaco-editor* `"@monaco-editor/react": "^4.3.1"` ---> `"4.4.6"` – Sumax Apr 14 '23 at 06:45
3

I had the same issue with my project. There is a monaco-editor-webpack-plugin that handles these loader issues. But the latest version has some problems in it. So I installed monaco-editor-webpack-plugin@6.0.0 along with monaco-editor@0.30.1. Then you just have to add the plugin to webpack.

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');

module.exports = {
  // ...
  plugins: [
    new MonacoWebpackPlugin(),
  ],
};
Mohib Arshi
  • 830
  • 4
  • 13
2

I have the same problem as you in my Vue project.

Maybe you can handle it like this:

Download the source code of monaco-editor from GitHub

Modify the function buildESM and the function buildOneAMD in file monaco-editor/build/utils.js

eg: set target to es2015

function buildESM(options) {
    build({
        entryPoints: options.entryPoints,
        bundle: true,
        target: 'es2015',
        format: 'esm',
        define: {
            AMD: 'false'
        },
        banner: {
            js: bundledFileHeader
        },
        external: options.external,
        outbase: `src/${options.base}`,
        outdir: `out/release/${options.base}/esm/`,
        plugins: [
            alias({
                'vscode-nls': path.join(__dirname, 'fillers/vscode-nls.ts')
            })
        ]
    });
}

and then, npm run release and wait until it's done

npm run release

you get the folder monaco-editor/release, copy the contents of the folder release and paste into the folder modules/monaco-editor you created under your project.

in your project, modify the package.json, set monaco-editor to file:modules/monaco-editor, and npm install

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "monaco-editor": "file:modules/monaco-editor",
  }
}
npm install

It's my way to solve this problem above, if somebody find the better solution, please reply to me here.

Excuse me, my English is bad.

sharping
  • 21
  • 5
  • Thank you. I understand that you recompiled Monaco Editor yourself. – SoftTimur Jan 10 '22 at 13:20
  • I solved this issue by installing a specific version of the *monaco-editor* `"@monaco-editor/react": "^4.3.1"` ---> `"4.4.6"` – Sumax Apr 14 '23 at 06:44
1

We have found two temporary solutions:

The first solution is, by following this thread, to use the follows in package.json:

"browserslist":[
    ">0.2%",
    "not dead",
    "not op_mini all"
]

The second solution is, to use import * as monaco from 'monaco-editor/esm/vs/editor/editor.api' rather than import * as monaco from 'monaco-editor'.

These two solutions bypass the error of optional chaining syntax. We have not found a direct way to deal with babel, babel-loder, react-app-rewired, etc.

SoftTimur
  • 5,630
  • 38
  • 140
  • 292