xdan / jodit

Jodit - Best WYSIWYG Editor for You
https://xdsoft.net/jodit/
MIT License
1.66k stars 351 forks source link

Image upload does not work after building for production version #157

Open anindya-dhruba opened 5 years ago

anindya-dhruba commented 5 years ago

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.

marchaos commented 5 years ago

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

mirk8xr commented 5 years ago

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.

marchaos commented 5 years ago

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.

dsmackie commented 5 years ago

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.

TomaszChmielPagepro commented 5 years ago

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
      }
    })
  ]
}
alexbet commented 5 years ago

I also have the same issue in production.

marlosirapuan commented 5 years ago

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

marlosirapuan commented 5 years ago

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! 👍

Lequoa commented 5 years ago

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.

jimerino commented 5 years ago

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, // Notemangle.propertiesisfalseby default. module: false, output: null, toplevel: false, nameCache: null, ie8: false, keep_classnames: undefined, keep_fnames: true, safari10: false } }) ] }

DigitVE commented 5 years ago

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

   mix.options({
       uglify: {
           uglifyOptions: {
               mangle: {
                   reserved: ['Jodit'],
               },
           },
       },
   })
jclapadula commented 5 years ago

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, // Notemangle.propertiesisfalseby 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!

shivam4786 commented 5 years ago

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, // Notemangle.propertiesisfalseby 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

m-maharjan commented 5 years ago

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'],
         },
      }
   }
})
songoten28 commented 5 years ago

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

mahendrakulkarni177 commented 4 years ago

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.

596868636 commented 4 years ago

英文水平不好,看的好吃力,全部看完,发现还是不能用,还是一样的问题。 环境: 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 } })

搞定