Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage with untranspiled module in node_modules? #689

Closed
zth opened this issue Jul 1, 2018 · 6 comments
Closed

Usage with untranspiled module in node_modules? #689

zth opened this issue Jul 1, 2018 · 6 comments

Comments

@zth
Copy link

zth commented Jul 1, 2018

Hi!

I'm trying to use a lib that ships untranspiled to NPM, and thus needs transpiling locally in the Razzle-project. I modified my razzle-config to include the module for transpilation in the js loader, and that seems to work fine for the client build as it no longer errors. However, I get the "unexpected token import"-error in what I assume is the server build.

Any ideas about this? I guess the problem is that I'd somehow need the module to be transpiled for the server as well?

Thanks in advance!

@zth
Copy link
Author

zth commented Jul 2, 2018

Managed to solve it. For future reference:

Turns out webpack-node-externals is applied and used during SSR, meaning no modules from node_modules are included for bundling and thus transpiling. I solved it by doing something along these lines in my razzle.config.js:

config.externals = target === 'node' ? [
      nodeExternals({
        whitelist: [
          dev ? 'webpack/hot/poll?300' : null,
          /\.(eot|woff|woff2|ttf|otf)$/,
          /\.(svg|png|jpg|jpeg|gif|ico)$/,
          /\.(mp4|mp3|ogg|swf|webp)$/,
          /\.(css|scss|sass|sss|less)$/,
          /^my-untranspiled-package/
        ].filter(Boolean),
      }),
    ] : [];

...where a majority of that code is copied right from createConfig.js in this repo.

@zth zth closed this as completed Jul 2, 2018
@rastyagaev
Copy link

@zth thank you!!

@MrLoh
Copy link
Contributor

MrLoh commented Sep 5, 2018

@zth how did you get it to work on the client side in the first place? could you share your config?

@MrLoh
Copy link
Contributor

MrLoh commented Sep 5, 2018

Ok, I figured it out. You need to extend the includes of the babel-loader. Also you have to set the babelOptions explicitly unless they are specified in a .babelrc inside the untranspiled package, having a /babelrc in your apps package is not enough.

Here's a complete example config:

'use strict';
const nodeExternals = require('webpack-node-externals');
const fs = require('fs');

module.exports = {
  modifyBabelOptions() {
    return {
      presets: ['razzle/babel'],
      plugins: ['transform-flow-strip-types'],
    };
  },
  modify(config, { target, dev }, webpack) {
    // package un-transpiled packages
    const babelRuleIndex = config.module.rules.findIndex(
      (rule) => rule.use && rule.use[0].loader && rule.use[0].loader.includes('babel-loader')
    );
    config.module.rules[babelRuleIndex] = Object.assign(config.module.rules[babelRuleIndex], {
      include: [
        ...config.module.rules[babelRuleIndex].include,
        fs.realpathSync('./node_modules/untranspiled-package')
      ],
    });
    config.externals =
      target === 'node'
        ? [
            nodeExternals({
              whitelist: [
                dev ? 'webpack/hot/poll?300' : null,
                /\.(eot|woff|woff2|ttf|otf)$/,
                /\.(svg|png|jpg|jpeg|gif|ico)$/,
                /\.(mp4|mp3|ogg|swf|webp)$/,
                /\.(css|scss|sass|sss|less)$/,
                /^untranspiled-package/,
              ].filter(Boolean),
            }),
          ]
        : [];
    // return
    return config;
  },
};

@nettiopsu
Copy link

I managed to do the same trick as @MrLoh also for Typescript ts-loader. Check allowedPackages, you can insert your package name there. I also took into account an idea that it seems that it is enough for current version of Razzle to be without custom config.externals, but you might be interested also in original @MrLoh solution (see about config.externals deletion: #842 (comment))

  const allowedPackages = ['my-component']

  const allowedPackagePaths = allowedPackages.map(packageName =>
    fs.realpathSync('./node_modules/' + packageName)
  )

  const tsRuleIndex = config.module.rules.findIndex(
    rule =>
      rule.use && rule.use[0].loader && rule.use[0].loader.includes('ts-loader')
  )

  if (tsRuleIndex === -1) {
    throw Error(
      'This component assumes that you are using ts-loader. If you are not using it, then you might need to check and test code for how would it work with other loaders'
    )
  }

  config.module.rules[tsRuleIndex] = {
    ...config.module.rules[tsRuleIndex],

    include: [
      ...config.module.rules[tsRuleIndex].include,
      ...allowedPackagePaths,
    ],
  }

  delete config.externals

@vitorcamachoo
Copy link

This worked with me. My question is, The libraries are being duplicated in the client and server bundle. Any way to chunk this common this into a new file using razzle.config.js ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants