jodit icon indicating copy to clipboard operation
jodit copied to clipboard

Image upload does not work after building for production version

Open anindya-dhruba opened this issue 6 years ago • 17 comments

I am trying to upload image in a react application. I have used the jodit-react library for this. This worked fine in development mode. But after pushing to production, it didn't. It was throwing an error in the bottom right side of the editor saying Need URL for AJAX request. Considering that might be a problem of jodit-react library, I tried to use the original one. But this was also throwing the same error.

Jodit Version: 3.2.44

Code

import React, {Component} from "react";
import buttons from './customButtons';
import 'jodit/build/jodit.min.js';

class CustomEditor extends Component {
  editor;
  editorRef = React.createRef();

  config = {
    uploader: {
      buttons,
      url: 'https://xdsoft.net/jodit/connector/index.php?action=fileUpload'
    }
  };

  componentDidMount() {
    this.createEditor();
  }

  createEditor() {
    this.editor && this.editor.destruct();
    this.editor = new Jodit(this.editorRef.current, this.config);

    this.editor.value = this.props.content;
    this.editor.events.on('change', this.props.onChange);
  }

  componentWillUnmount() {
    this.editor && this.editor.destruct();
  }

  render() {
    return (
      <textarea ref={this.editorRef}/>
    );
  }
}

export default CustomEditor;

Expected behavior: Image upload should work in both production and development mode in react.

Actual behavior: screenshot 2019-03-04 at 9 16 13 pm

Note: I could have created the issue under jodit-react repo, but that one doesn't look very active like this one. But in case you want to move it there, kindly let me know.

anindya-dhruba avatar Mar 04 '19 15:03 anindya-dhruba

Just tested this and I'm seeing the same thing.

marchaos avatar Mar 05 '19 11:03 marchaos

Same thing in production mode! It's like he did not take part of the given configuration.

By inspecting in the console the editor object created you can see how it does not have all the configurations given to the uploader options.

mirk8xr avatar Mar 08 '19 10:03 mirk8xr

The issue is in isJoditObject:

export const isJoditObject = (jodit: unknown): jodit is IJodit  => {
    if (jodit && jodit instanceof Object && typeof jodit.constructor === 'function' && jodit.constructor.name === 'Jodit') {
        return true;
    }

    return false;
};

jodit.constructor === 'function' && jodit.constructor.name === 'Jodit' does not work since the constructor name gets mangled, so this returns false for jodit.constructor.name === 'Jodit' You are better off setting boolean within the Jodit class isJodit = true.

marchaos avatar Mar 11 '19 11:03 marchaos

You can configure the minimizer to ignore the Jodit function name during mangle. I achieve this in Vue by editing vue.config.js as follows;

module.exports = {
  configureWebpack: config => {
    const terserOptions = config.optimization.minimizer[0].options.terserOptions;

    // Set regex to ignore Jodit function name
    terserOptions.keep_fnames = /^Jodit/;
  }
}

How you would do this in React I am not sure. But I am sure it would be similar.

dsmackie avatar Mar 26 '19 13:03 dsmackie

If you are using Webpack 3 and UglifyJsPlugin this will work:

webpack.config.js:

module.exports = {
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      mangle: {
        keep_fnames: true
      }
    })
  ]
}

TomaszChmielPagepro avatar Apr 09 '19 18:04 TomaszChmielPagepro

I also have the same issue in production.

alexbet avatar Apr 10 '19 16:04 alexbet

+1 localhost works.. in production, not..

marlosirapuan avatar May 07 '19 17:05 marlosirapuan

The issue is in isJoditObject:

export const isJoditObject = (jodit: unknown): jodit is IJodit  => {
    if (jodit && jodit instanceof Object && typeof jodit.constructor === 'function' && jodit.constructor.name === 'Jodit') {
        return true;
    }

    return false;
};

jodit.constructor === 'function' && jodit.constructor.name === 'Jodit' does not work since the constructor name gets mangled, so this returns false for jodit.constructor.name === 'Jodit' You are better off setting boolean within the Jodit class isJodit = true.

Worked here. Thank you! 👍

marlosirapuan avatar May 08 '19 19:05 marlosirapuan

Hi, I am still having this issue, check my below code:

declare var Jodit; public editor: any; ngOnInit() { this.editor = new Jodit('#sourceCode', { uploader: { url: '', insertImageAsBase64URI: true } }); }

NB: I just want to save the image uploaded as base64URI hence I made my URL empty.

It works locally but it is not working in production mode gives me Need URL for AJAX request.

Please help guys, I've been pulling my hair since the beginning of the week.

Lequoa avatar May 29 '19 10:05 Lequoa

If you use WebPack4, the solution is install terser-webpack-plugin

npm install terser-webpack-plugin --save-dev

and in module.export put:

optimization: { minimizer: [ new TerserPlugin({ terserOptions: { ecma: undefined, warnings: false, parse: {}, compress: {}, mangle: true, // Note mangle.propertiesisfalse by default. module: false, output: null, toplevel: false, nameCache: null, ie8: false, keep_classnames: undefined, keep_fnames: true, safari10: false } }) ] }

jimerino avatar Jun 03 '19 15:06 jimerino

Workaround for this issue for Laravel Mix, use config below in webpack.mix.js:

   mix.options({
       uglify: {
           uglifyOptions: {
               mangle: {
                   reserved: ['Jodit'],
               },
           },
       },
   })

DigitVE avatar Jun 14 '19 12:06 DigitVE

If you use WebPack4, the solution is install terser-webpack-plugin

npm install terser-webpack-plugin --save-dev

and in module.export put:

optimization: { minimizer: [ new TerserPlugin({ terserOptions: { ecma: undefined, warnings: false, parse: {}, compress: {}, mangle: true, // Note mangle.propertiesisfalse by default. module: false, output: null, toplevel: false, nameCache: null, ie8: false, keep_classnames: undefined, keep_fnames: true, safari10: false } }) ] }

Hi there, this fixed the issue for me, but the only configuration that is strictly needed is:

optimization: {
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            keep_fnames: true,
          },
        }),
      ],
    },

All the other default settings can be avoided.

Thanks anyway!

jclapadula avatar Jul 15 '19 13:07 jclapadula

If you use WebPack4, the solution is install terser-webpack-plugin

npm install terser-webpack-plugin --save-dev

and in module.export put:

optimization: { minimizer: [ new TerserPlugin({ terserOptions: { ecma: undefined, warnings: false, parse: {}, compress: {}, mangle: true, // Note mangle.propertiesisfalse by default. module: false, output: null, toplevel: false, nameCache: null, ie8: false, keep_classnames: undefined, keep_fnames: true, safari10: false } }) ] }

Thanks it worked for me, but, images not showing up after some time in editor

shivam4786 avatar Jul 18 '19 09:07 shivam4786

For laravel mix, if its version is 4 or higher use the following config in webpack.mix.js

mix.options({
   terser: {
      terserOptions: {
         mangle: {
            reserved: ['Jodit'],
         },
      }
   }
})

m-maharjan avatar Aug 13 '19 10:08 m-maharjan

In react ( nextjs)

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

 webpack: (config, {dev}) => {
...
if (!dev) {
            //bug https://github.com/xdan/jodit/issues/157
            config.optimization.minimizer = [
                new TerserPlugin({
                    parallel: true,
                    cache: true,
                    sourceMap: true,
                    terserOptions: {
                        safari10: true,
                        keep_fnames: /^Jodit/
                    },
                }),
            ];
        }
...
}

Check in config at your webpack

songoten28 avatar Aug 16 '19 06:08 songoten28

I found the solution which works on both development and production build..

solved using UglifyJsPlugin, config changes in webpack..

optimization: { minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true, extractComments: false, uglifyOptions: { ie8: false, mangle: { reserved: ['Jodit'], }, compress: { if_return: true, unused: true, booleans: true, properties: true, dead_code: true, pure_getters: true, unsafe: true, unsafe_comps: true, drop_console: true, passes: 2 }, output: { comments: false, beautify: false, }, minimize: true } }), ], },

I found this config setting in jodit editor demo project.. https://xdsoft.net/jodit/

download project and check in the webpack config file.

mahendrakulkarni177 avatar Oct 10 '19 05:10 mahendrakulkarni177

英文水平不好,看的好吃力,全部看完,发现还是不能用,还是一样的问题。 环境: iview + webpack 3

最后看着样子画瓢搞好了 把系统的new webpack.optimize.UglifyJsPlugin 整个删除,估计自带的压缩有问题

然后 加载webpack3的uglifyjs npm i uglifyjs-3-webpack-plugin

引入 const UglifyJsPlugin = require('uglifyjs-3-webpack-plugin')

配置 new UglifyJsPlugin({ cache: true, parallel: true, extractComments: false, uglifyOptions: { ie8: false, mangle: { reserved: ['Jodit'], }, compress: { if_return: true, unused: true, booleans: true, properties: true, dead_code: true, pure_getters: true, unsafe: true, unsafe_comps: true, drop_console: true, passes: 2 }, output: { comments: false, beautify: false, }, minimize: true } })

搞定

596868636 avatar Oct 18 '19 15:10 596868636