Tutorial: Adding node modules to Frappe

In some case you might want to add node_modules which can use in custom apps.

My use case is I want to add TinyMCE to blog post doctype.

Steps

  1. Create package.json

    npm init
    
  2. Install package, in my case I want to add tinymce package

    npm i tinymce
    
  3. Run bench build, bench build will

    • Create symbolic link from node_modules to public/node_modules
    • Create assets
      • Note
        • Frappe use rollup.js to create module bundler
        • public folder can be accessible from website url such as http://yourwebsite.com/assets/your_custom_app_name/...
        • build.json should be locate on public folder inside your custom apps
        • You cannot use concat in build.json in your custom apps, since it’s hard coded to run concat only on frappe apps
        • You cannot use import inside doctype js since it need to run through rollup.js frist
        • You could use import inside public folder and then use build.json to bundle the module
        • To manually run rollup.js for your custom apps, you could run /usr/bin/yarn node rollup/build.js --app your_custom_app_name
  4. Adding node_modules to doctype or apps, you need to use hook.py, here is what i did

    • OPTION A

      node_modules = {
      	'tinymce': {
      		'js': [
      			'assets/your_app_name/node_modules/tinymce/tinymce.min.js',
      			'assets/your_app_name/node_modules/tinymce/themes/mobile/theme.min.js',
      			'assets/your_app_name/node_modules/tinymce/themes/silver/theme.min.js',
      			'assets/your_app_name/node_modules/tinymce/icons/default/icons.min.js',
      		],
      	}
      }
      app_include_js = node_modules.get('tinymce').get('js')
      
    • OPTION B

      node_modules = {
      	'tinymce': {
      		'js': [
      			'public/node_modules/tinymce/tinymce.min.js',
      			'public/node_modules/tinymce/themes/mobile/theme.min.js',
      			'public/node_modules/tinymce/themes/silver/theme.min.js',
      			'public/node_modules/tinymce/icons/default/icons.min.js',
      		],
      	}
      }
      
      doctype_js = {
      	'Blog Post': node_modules.get('tinymce').get('js'),
      }
      

      Note
      - This won’t work if module need css, since it will try to access css file from http://yourwebsite.com/... such as http://yourwebsite.com/skins/content/default/content.css
      - JS still won’t work, I think it might be because loading sequence

    • OPTION C

      hook.py

      node_modules = {
      	'tinymce': {
      		'css': [
      			'assets/your_app_name/node_modules/tinymce/skins/ui/oxide/content.min.css',
      			'assets/your_app_name/node_modules/tinymce/skins/content/default/content.css',
      			'assets/your_app_name/node_modules/tinymce/skins/ui/oxide/skin.min.css',
      		]
      	}
      }
      
      app_include_css = node_modules.get('tinymce').get('css')
      

      your doctype js

      frappe.require([
        'assets/your_app_name/node_modules/tinymce/tinymce.min.js',
        'assets/your_app_name/node_modules/tinymce/themes/mobile/theme.min.js',
        'assets/your_app_name/node_modules/tinymce/themes/silver/theme.min.js',
        'assets/your_app_name/node_modules/tinymce/icons/default/icons.min.js',
      ], () => {
        tinymce.init({
      	selector: '#tiny_mce_editor',
      	height: 500,
        });
      });
      

      Note
      - Javascript will still try to access css from http://yourwebsite.com/skins/content/default/content.css but it will work since we’ve adding css to hook.py

Related link
- New Build System: Rollup
- How to add a node module to a custom app? - #2 by igrekus
- New Build System: Rollup by netchampfaris · Pull Request #5010 · frappe/frappe · GitHub


Please correct me if my understanding is incorrect.

8 Likes

Little off-topic, but if you want TinyMCE in your frappe installation you can use GitHub - shridarpatil/frappe_tinymce: Frappe app to replace default text editor with tinymce.
This replaces frappe’s Quill Text Editor with TinyMCE Text Editor

4 Likes

Hi, thanks for your tutorial.
where do I init ?
in bench or in my custom app?
do you have a document better than this or video tutorial ??
here you did not write where must do these codes…

1 Like

We should be able to use @import in our custom SCSS files, correct?

I’m referring to something such as:

@import "~example_module/base-styles/colors";

For some reason, I’m getting this error on app build:

error: Can't find stylesheet to import.
  ╷
1 │ @import "~example_module/base-styles/colors";
  │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ╵
  ../frappe_app/frappe_app/public/css/frappe_app.scss 1:9  @import

How can I include SCSS from node_modules in SCSS?

there’s a bug in this app, let’s say I edited the description in item number 01 and then i switch to any other item for example item 03,
the description shows the same as 01 until and unless I refresh the page, and this keeps on happening every time.