skip to Main Content

I’m integrating an existing React app into Next.js for mainly SEO features.

i pasted the css files links inside the <Header> tag in Next.js and they seem to work just fine. when i tried to do the same with the javascript files using the <script> tag, it doesn’t execute the code inside those scripts. but i can see them loaded with http 200 in the chrome dev tools.

I tried using a library called Loadjs from npm to load the scripts inside componentDidMount but i got the exact same result as using <script> tag.

is there a proper way to do such simple thing in Next.js that i’m not aware of ?

Here’s the code included in the pages/index.js file.

  import React from "react"
  import Head from 'next/head'
  import MyAwesomeComponent from "../components/mycomponent.js"
  export default () => (
    <div>
      <Head>

        <link type="text/css" rel="stylesheet" href="static/css/chatwidget.css" />
        <link type="text/css" rel="stylesheet" href="static/css/download.css" />

        <script type="text/javascript" src="static/libs/jquery.min.js"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/jquery.mCustomScrollbar.concat.min.js"></script>
        <script type="text/javascript" src="static/libs/bootstrap.min.js"></script>
        <script type="text/javascript" src="static/libs/owl.carousel.min.js"></script>
        <script type="text/javascript" src="static/scripts/chatHead.js"></script>
        <script type="text/javascript" src="static/libs/jquery.magnific-popup.js"></script>
      </Head>

      <MyAwesomeComponent /> {/* a simple React component that returns  : <p>Hello World </p>*/}
    </div>
  )

Sorry for the late answer.
it turned out that all the scripts i linked missed one script that would actually run the functions for each action.

8

Answers


  1. This works to me:

    Create a folder for your static files:

    <root>/public/static/script.js

    in your index.js at <root>/pages/index.js

    import Head from 'next/head';
    import MyAwesomeComponent from '../components/mycomponent';
    
    export default () => (
      <div>
        <Head>
          <script type="text/javascript" src="/static/script.js"></script>
        </Head>
        <MyAwesomeComponent />
      </div>
    )
    

    Note that static is the name I used in this example, it’s not a requirement, it would work with any other folder name.

    Login or Signup to reply.
  2. May this helps you Nextjs public folder

    Move your static folder into public folder in your root directory

    export default () => (
        <div>
          <Head>
    
            <link type="text/css" rel="stylesheet" href="/static/css/chatwidget.css" />
            <link type="text/css" rel="stylesheet" href="/static/css/download.css" />
    
            <script type="text/javascript" src="/static/libs/jquery.min.js"></script>
            ...
          </Head>
    
          <MyAwesomeComponent /> 
        </div>
      )
    
    Login or Signup to reply.
  3. You can also run js code this

              <script
                dangerouslySetInnerHTML={{
                  __html: `
                          let a = 1;
                          functionCall();
                      `,
                }}
              ></script>
    Login or Signup to reply.
  4. With the below approach you can easily put a script file’s raw script text into a generated Next.js HTML page’s <head> without screwing around with character escaping, formatting and general pretending that we aren’t actually just building an HTML page in the end anyways.

    There are many use cases you may want a script to run without going to network. Ex: 3rd party scripts, monitoring / analytics scripts that expect to be in the <head> without a separate network load. Many of these come minified, mangled, you-name-it and are just supposed to be copy, paste, move on with life.

    Next.js makes this very hard pretending that everything with web development is magically React and Webpack all the time now (I wish right?)

    The best developer experience way I’ve found is to do this:

    _document.js

    ...
    <Head>
      <script type="text/javascript" dangerouslySetInnerHTML={{ __html: process.env.rawJsFromFile }}></script>
    </Head>
    ...
    

    next.config.js

    https://github.com/vercel/next.js/blob/canary/packages/next/next-server/server/config.ts#L33

    module.exports = {
      env: {
        rawJsFromFile: fs.readFileSync('./rawJsFromFile.js').toString()
      }
    }
    

    rawJsFromFile.js

    alert('Freedom!!!!!!!!!!!!!!!');
    // and other 3rd party script junk, heck even minified JS is fine too if you need
    

    Hope this saves someone from hours of frustration that I endured coming up with this… 😭

    Login or Signup to reply.
  5. This is what I tried and it worked for me.
    I used two files entry-script.js and main-script.js. I put these like this
    <root>/static/entry-script.js and <root>/static/main-script.js
    The content of entry-script.js is below.

    (function (d, t) {
      t = d.createElement("script");
      t.setAttribute("src", "/static/main-script.js");
      d.getElementsByTagName("head")[0].appendChild(t);
    })(document);
    
    

    and the main logic is in the file main-script.js.
    In the file _doucment.js of NextJS I included my file entry-script.js in body like below

    class MyDocument extends Document {
      render() {
        return (
          <Html>
            <Head>
              <link
                rel="stylesheet"
                href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
              />
            </Head>
            <body>
              <script
                type="text/javascript"
                src="/static/entry-script.js"
              ></script>
              <Main />
              <NextScript />
            </body>
          </Html>
        );
      }
    }
    
    export default MyDocument;
    
    MyDocument.getInitialProps = async (ctx) => {
      // Resolution order
      //
      // On the server:
      // 1. app.getInitialProps
      // 2. page.getInitialProps
      // 3. document.getInitialProps
      // 4. app.render
      // 5. page.render
      // 6. document.render
      //
      // On the server with error:
      // 1. document.getInitialProps
      // 2. app.render
      // 3. page.render
      // 4. document.render
      //
      // On the client
      // 1. app.getInitialProps
      // 2. page.getInitialProps
      // 3. app.render
      // 4. page.render
    
      // Render app and page and get the context of the page with collected side effects.
      const sheets = new ServerStyleSheets();
      const originalRenderPage = ctx.renderPage;
    
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
        });
    
      const initialProps = await Document.getInitialProps(ctx);
    
      return {
        ...initialProps,
        // Styles fragment is rendered after the app and page rendering finish.
        styles: [
          ...React.Children.toArray(initialProps.styles),
          sheets.getStyleElement(),
        ],
      };
    };
    
    
    Login or Signup to reply.
  6. With Next.js v11 and onward, you can use the Next component Script

    https://nextjs.org/blog/next-11#script-optimization

    <Script
      src="..."
      strategy="beforeInteractive"
    />
    
    Login or Signup to reply.
  7. I wrote an article elaborating on this question, hopefully it comes in handy:

    https://www.devtwins.com/blog/how-to-add-a-third-party-script-to-a-nextjs-website

    Login or Signup to reply.
  8. Or if you want to try another way to import Js file like I did

    import { useEffect } from "react";
    
    function MyApp({ Component, pageProps }) {
        useEffect(() => {
            import("../styles/bootstrap.bundle.min.js");
        }, []);
        return <></>
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search