Skip to content
This repository has been archived by the owner on Aug 4, 2021. It is now read-only.

Rollup with Typescript through Babel #255

Closed
denkristoffer opened this issue Sep 25, 2018 · 11 comments
Closed

Rollup with Typescript through Babel #255

denkristoffer opened this issue Sep 25, 2018 · 11 comments

Comments

@denkristoffer
Copy link
Contributor

I keep getting "Unexpected token" errors when trying to compile Typescript React components with Rollup and rollup-plugin-babel:

[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src/theme.ts (1:5)
1: type Color = string
        ^

My rollup.config.js:

export default [
  {
    input: 'src/index.ts',
    plugins: [
      nodeResolve({
        customResolveOptions: {
          moduleDirectory: 'src',
        },
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
      }),

      babel(),
    ],
    output: [
      { file: pkg.module, format: 'es' },
      { file: pkg.main, format: 'cjs' },
    ],
  },
]

I also have a .babelrc file that uses @babel/preset-typescript. It works fine when using @babel/cli.

Versions:

  • rollup: 0.66.2
  • rollup-plugin-babel: I tried with 4.0.3 and 4.1.0-0
  • @babel/core: 7.1.0

Am I doing something wrong here or should this work?

@Andarist
Copy link
Member

You also need to pass extensions to babel plugin (most probable cause of your issue)

@denkristoffer
Copy link
Contributor Author

Thanks @Andarist, that was it! extensions isn't mentioned in the README, so I created a small PR: #256

@kentor
Copy link

kentor commented Jan 26, 2019

Hmm extensions doesn't seem to work...

rollup.config.js:

import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';

export default {
  input: 'src/index.ts',
  output: {
    file: 'lib/index.js',
    format: 'cjs',
  },
  plugins: [
    resolve(),
    babel({
      exclude: 'node_modules/**',
      extensions: ['.js', '.jsx', '.ts', '.tsx'],
    }),
  ],
};

.babelrc.js:

module.exports = {
  presets: [
    ['@babel/preset-env', {modules: false, targets: {node: 'current'}}],
    ['@babel/preset-typescript'],
  ],
};

Error:

[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src/index.ts (6:17)
4: const [_bin, _prog, ...args] = process.argv;
5: 
6: const packageJson: {scripts?: {[key: string]: string}} = require(path.join(
                    ^

@Andarist
Copy link
Member

Please share a repository with the issue reproduced, without that I won't be able to diagnose the issue.

@zhaparoff
Copy link

zhaparoff commented Feb 1, 2019

Faced the same issue.

When running babel isolated - it successfully transpiles TypeScript to JS files.
But when trying to do the same using rollup and rollup-plugin-babel, it fails with:

/src/entity1.ts, ./src/entity2.ts → dist...
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\entity1.ts (3:28)
1: import * as Framework from "./framework";
2:
3: export function OnFormLoad(): void {
4: setVisibiltiy();
5: setDisabled();
Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
at error (\ts-bundler-boilerplate\node_modules\rollup\dist\rollup.js:3597:30)
at Module.error (\ts-bundler-boilerplate\node_modules\rollup\dist\rollup.js:14376:9)
at tryParse (\ts-bundler-boilerplate\node_modules\rollup\dist\rollup.js:14039:16)
at Module.setSource (\ts-bundler-boilerplate\node_modules\rollup\dist\rollup.js:14095:35)
at \ts-bundler-boilerplate\node_modules\rollup\dist\rollup.js:17409:20

Seems like rollup tries to load original sources and validate them, before they will be transpiled from TS to JS by babel. I'm not sure is this a plugin issue or rollup itself...

babel: 7.2.2
rollup: 1.1.2
rollup-plugin-babel: 4.3.2

Here is the repo.

npm run build:ru

@Andarist
Copy link
Member

Andarist commented Feb 1, 2019

@zhaparoff

  1. u need to remove include from rollup-plugin-babel options (or rewrite it). Currently you are passing a full path to it and I suspect this doesnt play along with how it's implemented - using standard createFilter from rollup-pluginutils ( https://github.com/rollup/rollup-pluginutils/blob/d15e5ad0f2bdbf6caa0dd587ec9a712dc2f7c8b7/src/createFilter.ts )
  2. you also need to configure rollup-plugin-node-resolve to resolve .ts extension
  3. and finally you can't use code-splitting with IIFE output

Working config:

import path from "path";
import babel from "rollup-plugin-babel";
import resolve from "rollup-plugin-node-resolve";

const rootDir = path.resolve(__dirname);
const dstDir = path.join(rootDir, "dist");

const extensions = [".ts", ".js"]

export default {
  input: {
    entity1: "./src/entity1.ts",
    entity2: "./src/entity2.ts"
  },
  output: {
    dir: dstDir,
    format: "cjs",
    name: "Xrm.Test"
  },
  plugins: [
    resolve({
      jsnext: true,
      extensions,
    }),
    babel({
      extensions
    })
  ]
};

@zhaparoff
Copy link

@Andarist

Thanks for looking into it and for quick response!

Unfortunately, although your suggestions fixed the issue, 'cjs' or other module format except browser one is not acceptable for my purposes =(

Basically, I need a single output JS file for each TS input, without external dependencies (SystemJS, require, whatever else) to put it into the <script> tag, with JS that will work in IE. I'm not intrested in code splitting, on the contrary, my primary goal is a bulk bundling, ideally with good tree-shaking. So I decided trying rollup, because it is known as better tool for library bundling, producing less wrapper code than webpack.

Probably, I need to use some other approach: generate config with a single input for each input file and run rollup with multiple configs. Or bundle first and run babel transpilaition after...

Anyway, thanks for your help and for another great opensource tool!

@Andarist
Copy link
Member

Andarist commented Feb 2, 2019

Well, if you want to have multiple script tags you can't go with no external dependencies (if u want to support IE). In any system you have to keep register of your dependencies which basically means that you have to have external dep for that - either SystemJS, or amd loader.

@zhaparoff
Copy link

zhaparoff commented Feb 2, 2019

Unfortunately, in my particular case all dependencies have to be managed manually, as in ancient times of Web 1.0 =(
Since they are stored in the DB as blobs, not in filesystem, they don't have fixed url (it is generated dynamically during web page generation), so can't be referenced by other scripts in any comfortable way. And there is no dependencies support OOTB in that system... So in the web page metadata I need to manually specify explicitly which script files with all their dependencies I'd like to load from DB into this particular page.

When you need to load few files on very few pages - it is possible to manage. But when you have over 100 pages and 5-10 scripts to load on each page - this turns into real dependency hell.
I have framework script with thousands LoC, included and loaded for every page, just to have one dependency instead of 5. But anyway it still isn't a solution, because I can't bundle ALL scripts into the single file - it will have megabyte (or even dozen) size and will be uncacheable, since any change will affect the whole bundle. And again, I will need a bundler to build such script.

So my idea was to refactor scripts to use TS and ES6 modules for dependency management, and generate one single script (supported by IE) for each page by babel and some bundler and register it. I don't care about traffic, size, caching and all these optimizations at the moment, since it is intranet application. All I want to achieve is to bundle and register the only file for each page, whithout creating a single monster-bundle.

Sorry for this longread, just want to explain why using any module loading system isn't possible in my case.

@Andarist
Copy link
Member

Andarist commented Feb 2, 2019

If you don't care about caching etc I would probably go with a single bundle per site (I don't mean a single monolithic bundle). Which actually sounds like something you have described that you want to do - if I got your intention right.

For that you just have to create (can be programatically) a rollup config per site, and not a single config with multiple entries (what you have tried to do).

It would look smth like this:

import path from "path";
import babel from "rollup-plugin-babel";
import resolve from "rollup-plugin-node-resolve";

const rootDir = path.resolve(__dirname);
const dstDir = path.join(rootDir, "dist");

const extensions = [".ts", ".js"]

export default [
  "./src/entity1.ts",
  "./src/entity2.ts",
].map(input => ({
  input,    
  output: {
    file: '[name].js',
    format: "iife",
    name: "Xrm.Test"
  },
  plugins: [
    resolve({
      jsnext: true,
      extensions,
    }),
    babel({
      extensions
    })
  ]
}));

DrSensor added a commit to DrSensor/bot-byte that referenced this issue Feb 4, 2019
- [npm start] remove typescript declaration file
- [npm start] use babel with typescript preset
- [npm build] use typescript compiler

references:
- rollup/rollup-plugin-babel#255
- rollup/rollup-plugin-typescript#129
- rollup/rollup-plugin-babel#271
- rollup/rollup-plugin-babel#279
- microsoft/TypeScript-Babel-Starter#29
@mwood23
Copy link

mwood23 commented Mar 6, 2019

For anyone using React with Typescript and running into this issue, you also need to add @babel/preset-react

.babelrc

{
  "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/typescript"],
  "plugins": [
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread"
  ]
}

rollup.config

import babel from 'rollup-plugin-babel'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'

const isProd = process.env.NODE_ENV === 'production'

const extensions = ['.js', '.jsx', '.ts', '.tsx']

const globals = {
  react: 'React',
  'react-dom': 'ReactDOM',
}

export default {
  input: './src/index.ts',

  output: [
    {
      file: './dist/index.js',
      format: 'umd',
      name: 'workingConfig',
      globals,
      sourcemap: true,
    },
    { file: './dist/index.module.js', format: 'es', globals, sourcemap: true },
  ],
  plugins: [
    resolve({ extensions }),
    commonjs({
      include: '**/node_modules/**',
      namedExports: {},
    }),
    babel({
      extensions,
      include: ['src/**/*'],
      exclude: 'node_modules/**',
    }),
  ],
  external: Object.keys(globals),
}

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

No branches or pull requests

5 participants