Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot read property 'acequire' of undefined #230

Closed
jefflewis opened this issue Jul 3, 2017 · 11 comments
Closed

Cannot read property 'acequire' of undefined #230

jefflewis opened this issue Jul 3, 2017 · 11 comments

Comments

@jefflewis
Copy link

Problem

I am getting this same issue (RE: #141, #179, #187 ) on V5.0.1. I've destroyed node_modules, cleared yarn cache, reinstalled modules with yarn, and still get this error. The simplest hello world app will fail if I try to import AceEditor from 'react-ace' in the file.

What should I look for in trying to get this to work? Is this some sort compilation error with brace/react-ace?

I get the same error if I try to directly include the compiled JS file:import AceEditor from '../node_modules/react-ace/dist/react-ace.js'

Sample code to reproduce your issue

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import AceEditor from 'react-ace'
import 'brace/mode/javascript'
import 'brace/theme/github'

class App extends Component {
  onChange(newValue, e) {
    console.log(newValue, e);
  }

  render() {
    <AceEditor
      mode="javascript"
      theme="github"
      onChange={this.onChange}
      name="editor"
    />
  }
}

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <App />,
    document.getElementById('themes-entry')
  )
})

References

#141, #179, #187

@securingsincity
Copy link
Owner

@jefflewis Are you using webpack to bundle? or something else? This is caused by brace being undefined. Perhaps it is a compilation issue but i think I need a little more info on your set up first to try to reproduce.

@jefflewis
Copy link
Author

jefflewis commented Jul 5, 2017

Yes, I'm using webpack with rails to load my apps. I stuck a debugger point into ace.js right before brace.default was being called, and can confirm that it is undefined.

I did notice that after running yarn install from my project directory, and navigating to ./node_modules/react-ace that react-ace's node_modules directory was empty. Attempting to yarn install or npm install from inside the react-ace directory fails with a syntax error of being unable to compile the ...style code in both app.js and split.js. Removing this results in a failure to compile at the first piece of JSX code in both app.js and split.js (inside the render method).

I've outlined my web pack configuration below. Let me know if I can be of any more help getting this sorted out.

The following is my web pack config:

  • shared.js (contains shared configuration between environments)
  • development.js (dev environment specific config)
  • configuration.js (base configuration)

My loaders include babel:

./loaders/babel.js

module.exports = {
  test: /\.js(\.erb)?$/,
  exclude: /node_modules/,
  loader: 'babel-loader'
}

./shared.js

// Note: You must restart bin/webpack-dev-server for changes to take effect

/* eslint global-require: 0 */
/* eslint import/no-dynamic-require: 0 */

const webpack = require('webpack')
const { basename, dirname, join, relative, resolve } = require('path')
const { sync } = require('glob')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin')
const extname = require('path-complete-extname')
const { env, settings, output, loadersDir } = require('./configuration.js')

const extensionGlob = `**/*{${settings.extensions.join(',')}}*`
const entryPath = join(settings.source_path, settings.source_entry_path)
const packPaths = sync(join(entryPath, extensionGlob))

module.exports = {
  entry: packPaths.reduce(
    (map, entry) => {
      const localMap = map
      const namespace = relative(join(entryPath), dirname(entry))
      localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry)
      return localMap
    }, {}
  ),

  output: {
    filename: '[name].js',
    path: output.path,
    publicPath: output.publicPath
  },

  module: {
    rules: sync(join(loadersDir, '*.js')).map(loader => require(loader))
  },

  plugins: [
    new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
    new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
    new ManifestPlugin({
      publicPath: output.publicPath,
      writeToFileEmit: true
    })
  ],

  resolve: {
    extensions: settings.extensions,
    modules: [
      resolve(settings.source_path),
      'node_modules'
    ]
  },

  resolveLoader: {
    modules: ['node_modules']
  }
}

./development.js

// Note: You must restart bin/webpack-dev-server for changes to take effect
var fs = require('fs')

const merge = require('webpack-merge')
const sharedConfig = require('./shared.js')
const { settings, output } = require('./configuration.js')

module.exports = merge(sharedConfig, {
  devtool: 'cheap-eval-source-map',

  stats: {
    errorDetails: true
  },

  output: {
    pathinfo: true
  },

  devServer: {
    clientLogLevel: 'none',
    https: settings.dev_server.https,
    host: settings.dev_server.host,
    port: settings.dev_server.port,
    contentBase: output.path,
    publicPath: output.publicPath,
    compress: true,
    headers: { 'Access-Control-Allow-Origin': '*' },
    historyApiFallback: true,
    watchOptions: {
      ignored: /node_modules/
    },
    https: {
      key: fs.readFileSync('/projects/cohub/cohub-key.pem'),
      cert: fs.readFileSync('/projects/cohub/cohub-cert.pem')
    }
  }
})

./configuration.js

// Common configuration for webpacker loaded from config/webpacker.yml

const { join, resolve } = require('path')
const { env } = require('process')
const { safeLoad } = require('js-yaml')
const { readFileSync } = require('fs')

const configPath = resolve('config', 'webpacker.yml')
const loadersDir = join(__dirname, 'loaders')
const settings = safeLoad(readFileSync(configPath), 'utf8')[env.NODE_ENV]

function removeOuterSlashes(string) {
  return string.replace(/^\/*/, '').replace(/\/*$/, '')
}

function formatPublicPath(host = '', path = '') {
  let formattedHost = removeOuterSlashes(host)
  if (formattedHost && !/^http/i.test(formattedHost)) {
    formattedHost = `//${formattedHost}`
  }
  const formattedPath = removeOuterSlashes(path)
  return `${formattedHost}/${formattedPath}/`
}

const output = {
  path: resolve('public', settings.public_output_path),
  publicPath: formatPublicPath(env.ASSET_HOST, settings.public_output_path)
}

module.exports = {
  settings,
  env,
  loadersDir,
  output
}

Finally, my package.json:

package.json

{
  "dependencies": {
    "autoprefixer": "^7.1.1",
    "babel-core": "^6.25.0",
    "babel-loader": "7.x",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-polyfill": "^6.23.0",
    "babel-preset-env": "^1.5.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "coffee-loader": "^0.7.3",
    "coffee-script": "^1.12.6",
    "compression-webpack-plugin": "^0.4.0",
    "css-loader": "^0.28.4",
    "extract-text-webpack-plugin": "^2.1.2",
    "file-loader": "^0.11.2",
    "glob": "^7.1.2",
    "js-yaml": "^3.8.4",
    "node-sass": "^4.5.3",
    "path-complete-extname": "^0.1.0",
    "postcss-loader": "^2.0.5",
    "postcss-smart-import": "^0.7.4",
    "precss": "^1.4.0",
    "prop-types": "^15.5.10",
    "rails-erb-loader": "^5.0.1",
    "react": "^15.5.4",
    "react-ace": "^5.0.1",
    "react-apollo": "^1.4.2",
    "react-dom": "^15.5.4",
    "resolve-url-loader": "^2.0.2",
    "sass-loader": "^6.0.5",
    "semantic-ui-react": "^0.70.0",
    "style-loader": "^0.18.2",
    "webpack": "^2.6.1",
    "webpack-manifest-plugin": "^1.1.0",
    "webpack-merge": "^4.1.0"
  },
  "devDependencies": {
    "babel-plugin-relay": "^1.1.0",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-es2015-destructuring": "^6.23.0",
    "babel-plugin-transform-object-rest-spread": "^6.23.0",
    "webpack-dev-server": "^2.4.5"
  }
}

@jimmybaker
Copy link

👍 Can confirm this happens to me as well though I can't tell if this is a problem with how rails runs web pack or if it's this library. I used yarn to install the react-ace then I'm using react-ace in two different javascript/packs. The first one works but the second fails with the acequire error.

@frostpuppet
Copy link

+1 for me. I hit this on 5.1 with basic rails webpacker setup.

@securingsincity
Copy link
Owner

This may be related to rails, it may not be. I'll try to reproduce by setting up a rails environment. have any of you @jimmybaker @frostpuppet @jefflewis tried installing brace separately through npm and seeing if that fixes the issue?

@jefflewis
Copy link
Author

I had installed brace separately, and so no change in behavior.

@kyleknighted
Copy link

I am using webpacker and Rails 5.1.4 with version 5.8.0 of react-ace
I am seeing this same issue and have tried to delete everything and clearing cache but still the issue arises. My only minimal difference in setup is that I am running a forked version of brace in order to use a custom mode & theme.
Currently using rails-ace-ap outside of React with no problems.

@spoonscen
Copy link

spoonscen commented Dec 14, 2017

@securingsincity Spent an hour of so debugging this. It seems to me that there is some way react-ace is bundled that the parent project doesn't work with.

I did try to install brace separately which does not fix the issue. Another note is this is a node app I am working in and not a rails app.

In the lib/ace.js file which is the entry point, if you throw a step debugger on this you can see that require is not defined. Unfortunately this does not throw the error, it allows the script to keep on chugging. When it reaches the _interopRequireDefault it creates _brace2.default and assigns the result of require('brace') to it. In this case the result of require('brace') is undefined. Spent some time playing with the webpack config with no results. Just some helpful information. No real solution.

screen shot 2017-12-13 at 8 51 48 pm

@kyleknighted
Copy link

kyleknighted commented Dec 14, 2017

@securingsincity I am able to get a custom rollup of the code editor working with the code below & brace lib. Note the (typeof window !== 'undefined') conditionals. If you remove them or try something differently it almost always crashes. I haven't dug in deep enough to fully grok why this is. Not sure if this will help with the debugging process, just wanted to share a jank way I was able to get brace/ace to render in a React within Rails environment.

import React, { Component } from 'react';
import PropTypes from 'prop-types';

if (typeof window !== 'undefined') {
  const ace = require('brace');
}

class CodeEditor extends Component {
  componentDidMount() {
    if (typeof window !== 'undefined') {
      const {
        editorId,
        onChange,
        setReadOnly,
        setValue,
        setOptions,
        theme,
        mode,
        enableBasicAutocompletion,
        enableLiveAutocompletion,
      } = this.props;

      require(`brace/mode/${mode}`);
      require(`brace/theme/${theme}`);

      const editor = ace.edit(editorId);
      ace.require('ace/ext/language_tools');
      this.editor = editor;
      editor.getSession().setMode(`ace/mode/${mode}`);
      editor.setTheme(`ace/theme/${theme}`);
      editor.on('change', e => onChange(editor.getValue(), e));
      editor.setReadOnly(setReadOnly);
      editor.setValue(setValue);
      editor.$blockScrolling = Infinity;
      editor.setOptions({
        enableBasicAutocompletion,
        enableLiveAutocompletion,
        ...setOptions,
      });
    }
  }

  shouldComponentUpdate() {
    return false;
  }

  render() {
    const { className, style, editorId } = this.props;

    return (
      <div id={editorId} style={style} className={className}></div>
    );
  }
}

CodeEditor.propTypes = {
  editorId: PropTypes.string,
  className: PropTypes.string,
  onChange: PropTypes.func,
  setReadOnly: PropTypes.bool,
  enableBasicAutocompletion: PropTypes.bool,
  enableLiveAutocompletion: PropTypes.bool,
  setValue: PropTypes.string,
  theme: PropTypes.string,
  mode: PropTypes.string,
  style: PropTypes.object,
  setOptions: PropTypes.object,
};

CodeEditor.defaultProps = {
  editorId: 'ace-editor',
  className: '',
  onChange: () => {}, // (value, event)
  setValue: '',
  setReadOnly: false,
  theme: 'github',
  mode: 'javascript',
  enableBasicAutocompletion: true,
  enableLiveAutocompletion: true,
  style: {
    height: '300px',
    width: '400px',
  },
  setOptions: {},
};

export default CodeEditor;

@KimRasmussen
Copy link

KimRasmussen commented Dec 28, 2017

I don't know if this is totally irrelevant, so I apologize if it is...

But, I have the same issue with using swagger-editor which embeds ace.
I have a vaadin application which works fine with an embedded swagger-editor, unless I also use the vaadin addon "aceeditor" which bundles another version of ACE. Once that version has been loaded first in my application, swagger-editor breaks with:
Uncaught TypeError: Cannot read property 'acequire' of undefined
at Object. (swagger-editor-bundle.js:173)

If I have not used the other version of ACE from this addon, it works fine.

On the other hand, that version breaks (listeners on text changes are not invoked) if swagger-editor has been loaded first.

In all cases, reloading the browser using F5 causes either swagger-editor or the aceeditor vaadin addon to work again if the opposite component was displayed first.

@securingsincity
Copy link
Owner

Hi all given it's been quite some time and no activity on this issue, I am closing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants