I have a Next.js project with TypeScript. I take a reference from official document resulting to the followings.
BundledEditor.jsx:
// ** https://www.tiny.cloud/docs/tinymce/6/react-pm-bundle/ **//
import { Editor } from '@tinymce/tinymce-react'
// remove ssr, otherwise will cause ReferenceError: navigator is not defined
// TinyMCE so the global var exists
// eslint-disable-next-line no-unused-vars
import tinymce from 'tinymce/tinymce'
// DOM model
import 'tinymce/models/dom/model'
// Theme
import 'tinymce/themes/silver'
// Toolbar icons
import 'tinymce/icons/default'
// Editor styles
import 'tinymce/skins/ui/oxide/skin.min.css'
// importing the plugin js.
// if you use a plugin that is not listed here the editor will fail to load
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/anchor'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/autoresize'
import 'tinymce/plugins/autosave'
import 'tinymce/plugins/charmap'
import 'tinymce/plugins/code'
import 'tinymce/plugins/codesample'
import 'tinymce/plugins/directionality'
import 'tinymce/plugins/emoticons'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/help'
import 'tinymce/plugins/image'
import 'tinymce/plugins/importcss'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/link'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/media'
import 'tinymce/plugins/nonbreaking'
import 'tinymce/plugins/pagebreak'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/quickbars'
import 'tinymce/plugins/save'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/table'
import 'tinymce/plugins/template'
import 'tinymce/plugins/visualblocks'
import 'tinymce/plugins/visualchars'
import 'tinymce/plugins/wordcount'
// importing plugin resources
import 'tinymce/plugins/emoticons/js/emojis'
// Content styles, including inline UI like fake cursors
/* eslint import/no-webpack-loader-syntax: off */
// import contentCss from 'tinymce/skins/content/dark/content.css'
import contentCss from '!!raw-loader!tinymce/skins/content/default/content.min.css'
import contentUiCss from '!!raw-loader!tinymce/skins/ui/oxide/content.min.css'
export default function BundledEditor(props) {
const { init, ...rest } = props
// note that skin and content_css is disabled to avoid the normal
// loading process and is instead loaded as a string via content_style
return (
<Editor
init={{
...init,
skin: false,
content_css: false,
content_style: [contentCss, contentUiCss, init.content_style || ''].join('\n')
}}
{...rest}
/>
)
}
I just import it on other file like this:
import BundledEditor from './BundledEditor';
It works, but if refresh, the page will show this error:
ReferenceError: navigator is not defined
So I change the import way like this:
// remove ssr, otherwise will cause ReferenceError: navigator is not defined
const BundledEditor = dynamic(() => import('../BundledEditor'), {
ssr: false
})
then fix the issue.
But when I try to type yarn build
to check the project.
It shows error:
info - Collecting page data ...ReferenceError: navigator is not defined
at /Users/motogod19/4iDPS/Sphere/sphere-brand-dev/node_modules/tinymce/tinymce.js:961:23
at Object.<anonymous> (/Users/motogod19/4iDPS/Sphere/sphere-brand-dev/node_modules/tinymce/tinymce.js:31525:3)
at Module._compile (node:internal/modules/cjs/loader:1254:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
at Module.load (node:internal/modules/cjs/loader:1117:32)
at Module._load (node:internal/modules/cjs/loader:958:12)
at Module.require (node:internal/modules/cjs/loader:1141:19)
at require (node:internal/modules/cjs/helpers:110:18)
at 3868 (/Users/motogod19/4iDPS/Sphere/sphere-brand-dev/.next/server/pages/apps/campaign/BundledEditor.js:28:33)
at __webpack_require__ (/Users/motogod19/4iDPS/Sphere/sphere-brand-dev/.next/server/webpack-runtime.js:25:42)
> Build error occurred
Error: Failed to collect page data for /apps/campaign/BundledEditor
I'm not familiar with Next.js, is any dynamic import should I do ?
navigator is not defined
means that you are bundling the code for server side, which do not have the browser related APIs. You need to bundle this for the client side (that is, for the browser).
The issue is because tinymce
do not support ssr (as evident from https://github.com/tinymce/tinymce/issues/3709)
Since you are using Next.js 13 and pages
router, change your BundleEditor.jsx
to below:
// ** https://www.tiny.cloud/docs/tinymce/6/react-pm-bundle/ **//
import React from 'react';
import { Editor } from '@tinymce/tinymce-react';
if (typeof window !== 'undefined') {
require('tinymce/tinymce');
require('tinymce/models/dom/model');
require('tinymce/themes/silver');
require('tinymce/icons/default');
require('tinymce/plugins/advlist');
require('tinymce/plugins/anchor');
require('tinymce/plugins/autolink');
require('tinymce/plugins/autoresize');
require('tinymce/plugins/autosave');
require('tinymce/plugins/charmap');
require('tinymce/plugins/code');
require('tinymce/plugins/codesample');
require('tinymce/plugins/directionality');
require('tinymce/plugins/emoticons');
require('tinymce/plugins/fullscreen');
require('tinymce/plugins/help');
require('tinymce/plugins/image');
require('tinymce/plugins/importcss');
require('tinymce/plugins/insertdatetime');
require('tinymce/plugins/link');
require('tinymce/plugins/lists');
require('tinymce/plugins/media');
require('tinymce/plugins/nonbreaking');
require('tinymce/plugins/pagebreak');
require('tinymce/plugins/preview');
require('tinymce/plugins/quickbars');
require('tinymce/plugins/save');
require('tinymce/plugins/searchreplace');
require('tinymce/plugins/table');
require('tinymce/plugins/template');
require('tinymce/plugins/visualblocks');
require('tinymce/plugins/visualchars');
require('tinymce/plugins/wordcount');
require('tinymce/plugins/emoticons/js/emojis')
}
// Editor styles
import 'tinymce/skins/ui/oxide/skin.min.css';
// Content styles, including inline UI like fake cursors
/* eslint import/no-webpack-loader-syntax: off */
// import contentCss from 'tinymce/skins/content/dark/content.css'
import contentCss from '!!raw-loader!tinymce/skins/content/default/content.min.css';
import contentUiCss from '!!raw-loader!tinymce/skins/ui/oxide/content.min.css';
export default function BundledEditor(props) {
const { init, ...rest } = props;
// note that skin and content_css is disabled to avoid the normal
// loading process and is instead loaded as a string via content_style
return (
<Editor
init={{
...init,
skin: false,
content_css: false,
content_style: [contentCss, contentUiCss, init?.content_style || ''].join('\n'),
}}
{...rest}
/>
);
}
Both npm run dev
and npm run build
works fine.
$ npm run build
> testmce@0.1.0 build
> next build
- info Linting and checking validity of types
- info Creating an optimized production build
- info Compiled successfully
- info Collecting page data
- info Generating static pages (4/4)
- info Finalizing page optimization
Route (pages) Size First Load JS
┌ ○ / 3.39 kB 80.3 kB
├ └ css/00a586533d958f8e.css 1.73 kB
├ /_app 0 B 76.9 kB
├ ○ /404 182 B 77.1 kB
├ λ /api/hello 0 B 76.9 kB
└ ○ /BundledEditor 473 kB 550 kB
└ css/3191dae2698bb014.css 11.8 kB
+ First Load JS shared by all 77.6 kB
├ chunks/framework-63157d71ad419e09.js 45.2 kB
├ chunks/main-c6c319de9f7d0316.js 29.4 kB
├ chunks/pages/_app-5fbdfbcdfb555d2f.js 296 B
├ chunks/webpack-1f3c29ac3f0dceed.js 2.06 kB
└ css/876d048b5dab7c28.css 706 B
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
○ (Static) automatically rendered as static HTML (uses no initial props)