Next.js: Добавить поддержку транспилируемых модулей внутри node_modules

Созданный на 9 янв. 2017  ·  103Комментарии  ·  Источник: vercel/next.js

Теперь некоторые из нас поставляют пакеты NPM (особенно компоненты), написанные на ES2015, без их транспилирования.

Это очень хорошая вещь, особенно если они будут использоваться в таком проекте, как Next.js или CRA (который выполняет транспиляцию). Они предлагают такие преимущества, как:

  • Нет необходимости транспилировать перед отправкой в ​​NPM
  • Воспользуйтесь преимуществами встряхивания деревьев Webpack 2

Но мы не можем сделать это сейчас, потому что исключаем все внутри node_modules из babel-транспиляции.

Итак, вот предлагаемое решение.

У нас есть запись в next.config.js для включения модулей, которые должны пройти через babel. Видеть:

module.exports = {
   transpileModules: [
     "my-component",
     "redux/src"
   ]
}
story feature request

Самый полезный комментарий

Чем больше я всерьез использую next.js и создаю вокруг него обширную библиотеку модулей, тем более важной становится эта функция. Это становится настоящей PITA, копирующей этап компиляции babel в моих внутренних модулях.

🚀🤖

Все 103 Комментарий

  • Почему это невозможно с расширением webpack() ?
  • transpileModules звучит лучше
  • Будем ли мы принимать регулярные выражения?

Почему это невозможно с расширением webpack ()?

Надеюсь, вы имеете в виду настраиваемую конфигурацию веб-пакета. Это выполнимо. Но это находится в существующем загрузчике. Получить это несколько сложнее.

transpileModules звучит лучше

Потрясающие. Я обновлю.

Будем ли мы принимать регулярные выражения?
Ага. Конечно.

Привет,

Поскольку я открываю свой собственный веб-сайт, я пробую новые технологии, такие как Lerna / Next / Styled ... и был бы рад предоставить скорейший отзыв по этому поводу.

Я обнаружил повторяющуюся проблему, когда я пытался импортировать / транспилировать модуль на основе CRA в моем модуле NextJs, но не знал, как выполнить транспиляцию (обратите внимание, что я хотел бы, чтобы мой модуль работал как автономный)

Я также заметил, что Babel, также основанный на Lerna, транспилирует каждый модуль перед тем, как раскрыть его, но мне кажется, что лучше сделать так, как предлагает @arunoda , и позволить клиентскому приложению сделать транспилирование.

Я хотел бы иметь единую конфигурацию babel для моего клиента и делиться этой конфигурацией со всеми моими развязанными модулями. Это, вероятно, не так просто, если я хочу сохранить возможность запускать свои модули как автономные, за пределами Next runner.

Мой текущий тестовый проект находится здесь: https://github.com/slorber/playground/ Я постараюсь обновить его, как только будет форк / PR. @arunoda , ты над этим работаешь?

@slorber в настоящее время мы сосредоточены на выпуске 2.0, дорабатываем все и ищем ошибки, насколько это возможно.

Я еще не начал работать над этим, но мы сможем сделать это сразу после 2.0.

Хорошо, я сделаю вилку. Я уже работаю с бета-версией 2.0.0, потому что я не создаю критически важный веб-сайт и не думаю, что webpack 1.13 разрешает поле jsnext: main / module .

Я не эксперт по сборщикам, но я бы предпочел использовать поле "модуль" в package.json, нет? Насколько я знаю, "main" кажется уже перенесенным кодом. Но поскольку конфигурация webpack позволяет включать / исключать транспиляцию, я не уверен, что это актуально. Какие-либо рекомендации по поводу того, какое из 3 полей я бы предпочел использовать?

@slorber Я думаю, что webpack поддерживает только main как и NPM. Вы можете использовать это.
Мы можем проверить путь к файлу в функции exclude в нашем next.conf.js

Хм, согласно тому, что я видел на практике против Next 2.x, я видел, что модуль работает (но не работает позже во время выполнения, потому что не передается), в то время как jsnext: main не работал (насколько я помню). Но это должно поддерживаться .

В любом случае, jsnext: main или module не кажется решением этой проблемы, поэтому для внутренних модулей компании, вероятно, будет достаточно просто включения транспиляции.

Сообщество не согласилось с одним подходом, верно? Например, я смог без проблем использовать react-youtube другой из коробки. Я предполагаю, что перед публикацией будет выполнено транспилирование большого количества модулей?

Ссылка: https://github.com/rauchg/blog/blob/master/components/post/youtube.js

Да, имеет смысл всегда транспилировать перед публикацией, потому что вы не знаете, кто / как будет использовать модуль, и вы не хотите заставлять клиента устанавливать соответствующие настройки babel для вашей библиотеки. Это то, что предлагает Rollup : опубликовать модуль, переданный по-разному, чтобы сборщик мог решить, какой использовать.

Но для внутренних пакетов компании настройки транспиляции могут быть одинаковыми для нескольких проектов (например, предустановка babel), и для меня имеет смысл позволить сборщику клиента переносить все зависимости компании.

Совершенно согласен с @slorber - это было бы очень удобно для внутренних модулей, если вы разбиваете свой проект и максимально изолируете вещи.

И @rauchg / @arunoda, поддерживающая RegExp, было бы действительно неплохо, поэтому у вас может быть одна запись, которая захватывает все внутренние модули компании, используя, скажем, пространство имен NPM org:

// next.config.js
module.exports = {
  transpileModules: [
    /^\@my-npm-org\/.*/
  ]
}

Красивое предложение @philcockfield

Эй, может, стоит предложить несколько предустановок. Мне кажется, что большинство инструментов (ссылка Lerna / npm ...) полагаются на символические ссылки, так почему бы не сделать что-то настолько простое, как:

`` javascript
module.exports = {
transpileModules: ["символические ссылки"]
}
`` ''

Чем больше я всерьез использую next.js и создаю вокруг него обширную библиотеку модулей, тем более важной становится эта функция. Это становится настоящей PITA, копирующей этап компиляции babel в моих внутренних модулях.

🚀🤖

Я работаю над этим сегодня :)

@philcockfield , попробуйте: https://github.com/zeit/next.js/pull/749

спасибо @arunoda

Итак, как прокомментировано в вашем PR, если он не поддерживает символические ссылки, функция будет немного ограничена, потому что она не будет работать со ссылкой npm или Lerna, а только для модулей npm, которые не переносятся (верно? Я не вижу других вариант использования, если вы не фиксируете модули внутри /node_modules )

Почему бы не поддерживать символические ссылки? это сложнее поддерживать?

Также я хотел протестировать вашу ветку в своем приложении, но не уверен, как это лучше всего сделать. Есть ли какая-нибудь известная процедура, чтобы мы могли легко протестировать ветку и не слишком больно для тестировщика? Я пробовал такие вещи, как:

  • npm install https://github.com/arunoda/next.js.git#add -706: сбой, потому что следующая папка / bin пуста в репозитории github
  • git clone вилки внутри / node_modules: без особого успеха (но это может быть из-за моих специфических настроек Lerna)

Как лучше всего протестировать вилку на данный момент?

Если вы хотите сделать это с помощью next.config.js : module.exports = { webpack: (config , тогда в config.module.rules есть несколько вещей, похоже, вам нужно изменить одно из этих правил или добавить одно? :

  { loader: 'babel-loader',
    include: '/Users/me/gh/guide/node_modules/next/dist/pages',
    options: 
     { babelrc: false,
       cacheDirectory: true,
       sourceMaps: 'both',
       plugins: [Object] } },
  { test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: 
     [ '/Users/me/gh/guide',
       '/Users/me/gh/guide/node_modules/next/dist/pages' ],
    exclude: [Function: exclude],
    query: 
     { babelrc: true,
       cacheDirectory: true,
       sourceMaps: 'both',
       presets: [] } } ]

С нетерпением жду предложенного более простого синтаксиса.

Извините за мое незнание, я не могу понять, как решить эту проблему? Мы бы хотели импортировать es6 в нашу кодовую базу, нам нужно встряхивание дерева.

Есть ли по этому поводу пиар?

@andrewmclagan Эта проблема все еще открыта и имеет связанный PR, который, вероятно, не удовлетворит всех (например, пользователей LernaJS)

Какой у этого статус? Есть ли другие способы заставить следующий веб-пакет переносить файлы, импортированные из node_modules?

@slorber, я посмотрю на PR. Поделитесь нашим вариантом использования.

Я столкнулся с похожей проблемой. Пытаюсь использовать пакет get-urls . Работает find с dev но когда я его компилирую. Я получил ошибку от uglify

...
{ Error: commons.js from UglifyJs
...

Есть ли способ обойти это, пожалуйста?

Когда-нибудь здесь Арунода поработает над этим. Он уже делал это раньше в # 749

Я бы хотел, чтобы эта функция была реализована. Как упоминалось в @philcockfield , это распространенный сценарий создания библиотеки модулей, зависящих от транспиляции Next.js, и было бы здорово иметь возможность совместно использовать компоненты между проектами.

Это нужно не только для тряски дерева. Также для плагинов babel, таких как styled-jsx . Поэтому, если у вас есть модуль (например, библиотека), который использует плагин babel, лучшим решением будет включить исходный код ES6 и позволить вашему приложению переносить его из node_modules. Конечно, следующий по умолчанию уже включает styled-jsx .

Вот что я сделал

// next.config.js
exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
  exclude: Object.prototype.toString.call(exclude) === '[object Function]' ? (str => !/mycomponents/.test(str) && exclude(str)) : exclude,
  ...rest
})), config);

Я в основном заменил каждый exclude пользовательской функцией.
Я не знаю, что делаю не так, но у меня просто не получается заставить это работать.
Мне нужно, чтобы содержимое node_modules/mycomponents также передавалось Next.js

Это даже не сработает, если я полностью переопределю все исключения с пустым массивом

exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
  exclude: [],
  ...rest
})), config);

Помогите, пожалуйста :)
Спасибо

Привет, ребята ( @thealjey ) Я уже несколько месяцев транспилирую модули на jsnext:main .

Я не использую next.js но надеюсь, что это поможет.

@damianobarbati нет, к сожалению, нет
Настроить webpack напрямую для транспиляции чего угодно несложно, но я изо всех сил пытаюсь заставить эту работу работать в контексте Next.js

Привет всем, кто-нибудь нашел решение?

У меня есть локальный модуль связанного узла ES6, который мне нужно импортировать в свой проект, но я не могу правильно получить webpack voodoo!

Я уверен, что есть способ получше, но мы запускаем все через babel при сборке:

next build && babel .next/*.js --out-dir . --presets=es2015,react

Это умерло? Я ищу способ транспилировать настраиваемый модуль, но, похоже, это все еще невозможно.

@mattfelten это есть в дорожной карте для v5 👍

У кого-нибудь есть пример обходного пути для этого?

@timneutkens Есть какие-то сроки для этого? Примите во внимание, что это часто невыполнимый вопрос, но мы пытаемся определить наш стек в работе на данный момент, и это довольно серьезный препятствие для нас! :)

Предложения по обходному пути также действительны.

@thealjey понимает, что это старый комментарий, но ваше решение, вероятно, не сработало, потому что также указан include который необходимо переопределить.

Обновление: изучил эту стратегию, но это просто неразумно, учитывая все разные загрузчики для разных каталогов модулей во внутренней конфигурации next.js. Это должно быть первоклассное.

@chrisui моим (временным) решением было использовать babel-plugin-module-resolver , настроенный следующим образом - "plugins": [["module-resolver", {"root": ["./"]}]]
это ни в коем случае не идеальное решение, но, поскольку все остальное не удалось, на данный момент оно работает
благодаря этому мне не нужно писать кучу ../ при каждом импорте
на самом деле это может быть лучшим решением для некоторых, хотя, безусловно, не помогает с возможностью повторного использования

@thealjey не могли бы вы привести пример?
У меня есть настройка проекта, в которой я пытаюсь это безрезультатно ...
https://github.com/jamesgorrie/nappy

Я бы с радостью попробовал получить PR, так как это сделало бы нашу жизнь намного проще, но есть несколько вопросов, например: Должен ли next.js поддерживать транспиляцию определенных модулей или это должно быть на усмотрение транспилятора, но next.js более строго следует разрешению модуля. Не уверен, у кого спросить или с чего начать, как новичок в next.js .

это в дорожной карте для v5 👍

@timneutkens это

интересно знать.

Вы только посмотрите, где он слился. это было объединено 8 дней назад. 5.0.0 была выпущена 2 дня назад. из ветки канареек, где это объединено в ...

Есть ли у кого-нибудь пример того, как это можно реализовать? Это должно работать так, как упоминалось выше?

module.exports = {
    transpileModules: ['my-npm-module']
}

или это выглядит иначе?

Я запутался. @timneutkens Вышеупомянутая ссылка на PR, который все еще открыт. Это еще НЕ было объединено в v5?

РЕДАКТИРОВАТЬ: Неважно, это просто пиар, чтобы выделить пример.

Это пример, вы можете использовать его без объединения. transpileModules - это то, чем мы займемся позже.

Общее практическое правило: когда проблема открыта, она не выпускается.

@brianyingling Я превратил этот пример в плагин для временного решения (только v5).
В настоящий момент это работает для нас, пока не будет введено более надежное официальное решение.

https://www.npmjs.com/package/@weco/next -plugin-transpile-modules

Я хотел бы увидеть пример этого для одного модуля в базе кода приложения.

Например, у меня есть модуль, который я использую как на стороне сервера, так и на стороне клиента. Мне не удалось заставить работать ни один из приведенных выше примеров ни путем разложения модуля на его собственный отдельный модуль и yarn link его, или путем взлома правил веб-пакетов.

Вот простой пример: https://github.com/statico/nextjs-with-async-lib

// pages/index.js
import { foo } from '../lib/test'
export default () => <div>hello {String(typeof foo)}</div>

// lib/test.js
async function foo () {}
module.exports = { foo }

@timneutkens сообщает мне, что это потому, что я использую async/await в общем модуле. Я предполагаю, что моим решением может быть удаление async / await и изменение всего на обратные вызовы в стиле .then() .

Хорошо, я нашел исправление, которое мне подходит.

Сначала я добавил настройку config.resolve.symlinks = false в свою конфигурацию next.config.js для https://github.com/zeit/next.js/issues/3018#issuecomment -380879576

// next.config.js
webpack: (config, { dev }) => {
  config.resolve.symlinks = false
  return config
}

Затем я помещаю свою общую библиотеку - файл .js который использует экспорт CommonJS и ключевые слова async / await - в подкаталог приложения с именем shared :

// shared/index.js
async function foo () {}
module.exports = { foo }
// shared/package.json
{
  "name": "@myapp/shared",
  "version": "1.0.0",
  "main": "index.js",
  "license": "UNLICENSED",
  "private": true,
  "dependencies": { ... }
}

И, наконец, я добавил postinstall скрипт, чтобы связать все вместе, когда кто-то выполняет yarn install в основном приложении:

// package.json
{
  ...
  "scripts": {
    "postinstall": "cd shared ; yarn -s unlink ; yarn link && yarn && cd .. && yarn link @myapp/shared",
   ...

Теперь мои тесты Mocha проходят на стороне сервера, мой собственный сервер Koa запускается нормально, и на моих страницах NextJS больше нет сумасшедших Cannot assign to read only property 'exports' of object '#<Object>' .

У меня была такая же проблема при обновлении до NextJs 5.1.0. Один или два из узловых модулей в следующем не передавали функции жирных стрелок и не выдавали ошибок в IE11. Раньше я настраивал отдельные полифиллы, и в конце концов я решил настроить таргетинг на эти файлы модулей с помощью babel-polyfill в моем next.config.js следующим образом:

module.exports = {
  webpack: (config, { dev }) => {
    const polyfill = new Promise((resolve, reject) => {
      const originalEntry = config.entry

      originalEntry().then(entries => {
        if (entries['main.js']) {
          entries['main.js'].unshift('./client/polyfills.js')
          entries['main.js'].unshift('babel-polyfill')
        }
        config.entry = entries

        resolve()
      })
    })

    config.module.rules.push(
     {
        test: path.resolve('./node_modules/next/node_modules/'),
        loader: 'babel-loader',
        options: {
          babelrc: false,
          cacheDirectory: false,
          presets: ['es2015']  
        }
      }
    )

    return polyfill.then(() => { return config })
  }
}

Надеюсь, это кому-то поможет.

ESM работает как шарм.

С настраиваемым сервером Next.js в index.js я могу запустить эту команду, чтобы запустить сервер, и esm отлично сработает, разрешая модули ES в пакетах проектов с символической связью Lerna.

node -r esm index.js

@curran круто, он может заменить babel-node?

@curran Я бы этого не делал в продакшене

@blackbing я не знаю.

@thealjey Почему?

Если кто-то ищет быстрое и простое решение, вот что я сделал. Я создал подкаталог shared/ с любым кодом, который мы хотим запустить как на бэкэнде через отдельный скрипт Node, так и на клиенте через NextJS. Он имеет собственный package.json и объявляет свое имя как @myproject/shared .

Затем в основном (родительском) проекте я добавил сценарий постустановки в package.json например: cd shared && yarn -s unlink >/dev/null 2>&1 ; yarn -s link && yarn -s && yarn link @myproject/shared - затем запустите yarn хотя бы один раз и измените свой импорт на import { whatever } from '@myproject/shared/somefile'

Таким образом, общий код работает без каких-либо сумасшедших шагов транспиляции, плюс вам не нужно повторно запускать yarn / npm каждый раз, когда вы делаете обновление, поскольку yarn link делает символическая ссылка.

Для тех, кто использует TypeScript, @weco/next-plugin-transpile-modules не должно работать. Я создал вилку для обработки Next withTypescript : https://github.com/KeitIG/next-plugin-transpile-modules

Тем не менее, мне все еще нужно понять, как все делать правильно, когда нам нужен серверный код и в TypeScript.

Есть новости по этому поводу?

@bogdansoare Я использую https://github.com/KeitIG/next-plugin-transpile-modules

И еще один, сделанный мной, в следующем смысле. Он обрабатывает TypeScript, а также определенные пакеты @scope , а не все пакеты. https://gist.github.com/trusktr/44400d0d016c506629b4f914799dc9cd

Я просто собрал простой рабочий пример, в котором используются esm и lerna

https://github.com/curran/nextjs-esm-example

/ cc @jdalton

Лично это работает со следующими next.config.js :

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: [
        options.defaultLoaders.babel
      ]
    })

    return config
  }
}

Он лепит все в node_modules , что мне нужно для достижения совместимости с IE 11 ...

Я также был бы признателен за решение для этого, борясь с добавлением непереносимых пакетов npm в мой проект. Пришлось загрузить их поставщику / на данный момент :(
Действительно раздражает

@ bel0v Я считаю, что вы уже сможете сделать это с помощью next-plugin-transpile-modules . Этот вопрос, скорее всего, следует закрыть. cc / @timneutkens

Я все еще хотел бы изучить альтернативные решения.

Недавно Джейми написал очень подробную ветку о проблеме компиляции node_modules: https://twitter.com/jamiebuilds/status/1080840492525350912

Я прочитал ветку Джейми, хотя я также хотел бы поделиться взглядом Генри Чжу и Бабеля на эту ситуацию и решение.
https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages

(Не возражаю с Тимом, просто подумал, что поделюсь множеством плюсов и минусов. Может помочь Тиму в поиске альтернативных решений)

Да, последние полгода мы обсуждали эту проблему со многими людьми, включая Генри 😄

Несмотря на опасения по поводу транспиляции node_modules, желание перенести свои собственные пакеты в монорепозиторий является очень распространенным требованием, к которому эти проблемы не относятся.

@dcalhoun Я пробовал, но, к сожалению, все еще получаю неожиданную ошибку токена. В этом плагине есть открытая проблема Next 7, которая может быть связана

@ bel0v

Вы должны прочитать FAQ;) есть решение этой проблемы: https://github.com/martpie/next-plugin-transpile-modules#i -have-Trouble-Making-it-work-with-nextjs-7

Я использовал этот плагин в нескольких проектах, и он отлично справляется со своей работой. Проблема Next 7 странная, я не уверен, исходит ли она от Next или Babel, я все равно открыл здесь проблему: https://github.com/zeit/next.js/issues/5393

@martpie да, я думаю, я пробовал это .. в любом случае я попробую еще раз

@martpie, мы начали использовать next7 с согласованными рабочими пространствами babel.config.js и yarn, я могу посмотреть, смогу ли я настроить простой пример.

Я развил базовый пример здесь
https://github.com/bel0v/learnnextjs-demo
в нем я установил нетранспилированную зависимость (wired-elements), получил ошибку сборки Unhandled Rejection (SyntaxError): Unexpected token { и попытался исправить предложенным способом.
Думаю, может мне понадобятся дополнительные плагины babel, чтобы он работал .. 🤔

@ bel0v снова в FAQ, есть объяснение, почему настройки Lerna не работают (TL, DR; вы, вероятно, используете неправильно)

@martpie а, понял! Не понимал, что сторонний пакет был настроен с помощью Лерны. Спасибо

Похоже, https://twitter.com/jamiebuilds был приостановлен, поэтому больше не могу читать там поток. # 3018 Ссылка на эту проблему закрыта, поэтому мне интересно, какие альтернативные подходы рассматриваются?
Отражают ли они современные / лучшие практики next.js для этих сценариев использования?
https://github.com/curran/nextjs-esm-example
https://github.com/wellcometrust/next-plugin-transpile-modules
https://github.com/martpie/next-transpile-modules
https://github.com/zeit/next.js/tree/canary/examples/with-yarn-workspaces

Итак, если вы, как и я, работаете над проектом, который должен поддерживать IE11, вам действительно нужно перенести весь код внутри node_modules/ . В Next.js 7.x я использовал следующую настройку, которая отлично работала.

К сожалению, он перестал работать в Next.js 8.x из-за ошибок, что модули не могли импортировать другие модули, потому что у них не было экспорта по умолчанию. Затем я придумал конфигурацию ниже для Next.js 8.x, которая переносит код только в node_modules/ с @babel/preset-env и никакими другими плагинами.

Это комбинируется путем установки моего свойства browserlist в package.json :

  "browserslist": "defaults, IE >= 11, EDGE >= 14, Safari >= 11, Chrome >= 41, Firefox >= 52",

Следующий 7.x

next.config.js

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: [
        options.defaultLoaders.babel,
      ],
    })

    return config
  },
}

Next.js 8.x

next.config.js

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
          plugins: ['@babel/plugin-syntax-dynamic-import'],
        },
      },
    })

    return config
  },
}

К сожалению, я еще не понял, как использовать @babel/plugin-transform-runtime с этой настройкой, поэтому он, вероятно, выплюнет довольно много помощников в коде 😞 надеюсь, что gzip позаботится об этом 😆 😅


Я думаю , что это было бы удивительным , если Next.js могли бы дать нам возможность , чтобы правильно transpile node_modules/ , чтобы работать с любым browserlist у вас есть. Похоже, что любые крупные сайты, у которых есть корпоративные пользователи, зависят от этого, чтобы должным образом поддерживать старые браузеры.

Как сопровождающий next-transpile-modules (основанный на потрясающей работе @jamesgorrie), я рад помочь любому, кто сталкивается с этой проблемой здесь.

Я работаю над профессиональными проектами более года с этим плагином, и пока он работает хорошо.

Встроенная поддержка Next.js, конечно, была бы замечательной, и я был бы рад помочь интегрировать эту функцию в пакет next . Я знаю, что у Тима были идеи, которые он хотел попробовать, но все равно.

Ваше здоровье!

@martpie Я быстро просмотрел ваш проект, но не нашел быстрого способа транспилировать _все_ модули, возможно ли это? ☺️

Кроме того, я вижу, что вы выбираете options.defaultLoaders.babel и используете его в качестве загрузчика babel. При выполнении этого с Next.js 8.x у меня возникла проблема, заключающаяся в том, что некоторые модули не могли быть должным образом распознаны как модуль CJS после этого, а затем другие библиотеки не смогли их импортировать, например:

./pages/_glamor.js
Attempted import error: 'css' is not exported from 'glamor'.

./components/project-selector.js
Attempted import error: 'react-select/lib/Async' does not contain a default export (imported as 'AsyncSelect').

./node_modules/react-select/dist/react-select.esm.js
Attempted import error: 'react-input-autosize' does not contain a default export (imported as 'AutosizeInput').

./pages/signup/full.js
Attempted import error: 'react-select/lib/Creatable' does not contain a default export (imported as 'CreatableSelect').

./components/markdown-editor.js
Attempted import error: 'react-simplemde-editor' does not contain a default export (imported as 'SimpleMDEEditor').

./components/pagination.js
Attempted import error: 'react-js-pagination' does not contain a default export (imported as 'UpstreamPagination').

./node_modules/react-google-recaptcha/lib/es/recaptcha-wrapper.js
Attempted import error: 'react-async-script' does not contain a default export (imported as 'makeAsyncScriptLoader').

./pages/_glamor.js
Attempted import error: 'rehydrate' is not exported from 'glamor'.

Вот почему я переключился на предоставление настраиваемой конфигурации babel для node_modules/ , которая транслирует код только с помощью preset-env и пропускает специфичные для Next.js преобразования. Что вы думаете об этом подходе?

Ура 🍻

@LinusU Может попробовать transpileModules: ['(.*?)'] и сказать мне, работает ли?

Но он может не работать в будущих основных версиях, поэтому будьте осторожны.

В более общем плане, я не рекомендую (читайте «крайне не рекомендуется») переносить всю папку node_modules , компиляция займет вечность, а пакеты должны содержать код, совместимый с ES3 (так что совместим с IE11).

Транспилируйте только тот модуль, который вам нужен! (например, lodash-es , локальные модули и т. д.)

пакеты должны предоставлять ES3-совместимый код (чтобы IE11-совместимый).

Но это не та реальность, которую я видел, и на самом деле я с этим не согласен. Авторы модуля никогда не узнают, на какие браузеры я нацелен, и если они отправят более старый код, они потенциально могут наказать пользователей, ориентированных на современные браузеры.

компиляция займет вечность

Для меня это немного медленно при запуске, но после этого кажется, что он кэшируется, и при внесении изменений на определенную страницу я вижу почти мгновенные перезагрузки.

Транспилируйте только тот модуль, который вам нужен!

Это потребовало бы, чтобы я точно знал, какие пакеты совместимы с IE11, а какие нет, а также постоянно обновлял эту информацию при изменении любых зависимостей (даже временных зависимостей). Не понимаю, насколько это реально 🤔

Важно то, что точки входа ESM, представленные в package.json module , обычно являются ES5 с импортом / экспортом ES6 для встряхивания дерева. Таким образом, это работа сборщика (Webpack), а не транспилятора (Babel), если не указано иное. Многие хорошо обслуживаемые пакеты уже имеют точки входа в ESM, например, redux/es для Redux, о котором упоминал OP.

Если вы хотите сделать это с помощью next.config.js : module.exports = { webpack: (config , тогда в config.module.rules есть несколько вещей, похоже, вам нужно изменить одно из этих правил или добавить одно? :

  { loader: 'babel-loader',
    include: '/Users/me/gh/guide/node_modules/next/dist/pages',
    options: 
     { babelrc: false,
       cacheDirectory: true,
       sourceMaps: 'both',
       plugins: [Object] } },
  { test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: 
     [ '/Users/me/gh/guide',
       '/Users/me/gh/guide/node_modules/next/dist/pages' ],
    exclude: [Function: exclude],
    query: 
     { babelrc: true,
       cacheDirectory: true,
       sourceMaps: 'both',
       presets: [] } } ]

С нетерпением жду предложенного более простого синтаксиса.

У меня отлично работает

{
    test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: [
        path.resolve(__dirname, './node_modules/next/dist/pages'),
    ],
    query: {
        cacheDirectory: true,
        sourceMaps: 'both',
        presets: ['@babel/preset-env'],
        plugins: ['@babel/plugin-proposal-object-rest-spread']
    }
},

Я столкнулся с этой проблемой, используя моно-репо Lerna, и ломал голову над тем, в чем была причина. Поскольку ошибка исходит из веб-пакета, она не дает подробных сведений, кроме того, что отсутствует загрузчик, что бесполезно. К счастью, я нашел эту проблему с github!

Я собираюсь оставить свое решение здесь для всех, кто ищет эту проблему и также использует Lerna:

Создайте сценарий предварительной публикации для общего пакета, который переносит исходный код в каталог dist и говорит Лерне указывать на каталог dist при связывании:

// package.json
"main": "dist",
"scripts": {
  // I'm using the react-app preset because it's easy
  "prepublish": "babel --presets react-app --plugins @babel/plugin-transform-modules-commonjs src --out-dir dist"
},
// This instructs Lerna to use dist when symlinking
"publishConfig": {
  "directory": "dist"
}

Теперь, когда вы lerna bootstrap он запустит сценарий предварительной публикации и перенесет исходный код, чтобы Next мог его использовать.

Если вы используете lerna вы можете создавать символические ссылки для транспиляции с помощью модулей next-transpile-modules . Как использовать этот пакет с lerna написано в конце документации.

Для тех, кто ищет общий доступ к коду в приложениях NextJs, я просто хотел бы сообщить, что решение @LinusU сработало для меня, когда я пытался поделиться компонентами и утилитами React между несколькими приложениями NextJs в моем монорепозитории:

// next.config.js
const aliasPathsToResolve = [
    { name: 'components', path: path.resolve(__dirname, './components') },
    { name: 'Common', path: path.resolve(__dirname, '../../common/react/') },
]
module.exports = () => {
    return  {
        webpack(config, { defaultLoaders }) {
            config.module.rules.push({
            test: /\.(js|jsx)$/,
            include: [path.resolve(__dirname, '../../common/react/')],
            use: [defaultLoaders.babel],
        })

            /** Resolve aliases */
        aliasPathsToResolve.forEach((module) => {
            config.resolve.alias[module.name] = module.path
        })
        }
    }
}

Я использую последнюю версию NextJs на момент написания этой статьи.

@ Lwdthe1 Я попробовал ваш код и сначала получил эту ошибку:

TypeError: Cannot read property 'then' of undefined
    at getBaseWebpackConfig (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/build/webpack-config.js:85:25)
    at async Promise.all (index 0)
    at async HotReloader.start (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/hot-reloader.js:14:1675)
    at async DevServer.prepare (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/next-dev-server.js:7:223)
    at async /c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/cli/next-dev.js:22:359

Сделал некоторые настройки и в итоге получил следующее:

const path = require("path");

const libPath = "../components/src"
const aliasPathsToResolve = [
  { name: "Common", path: path.resolve(__dirname, libPath) }
];

module.exports = {
  webpack: (config, { defaultLoaders }) => {
    config.module.rules.push({
      test: /\.(js|jsx)$/,
      include: [path.resolve(__dirname, libPath)],
      use: [defaultLoaders.babel]
    });

    /** Resolve aliases */
    aliasPathsToResolve.forEach(module => {
      config.resolve.alias[module.name] = module.path;
    });
    return config
  }
};

Но столкнулся с другой ошибкой:

export { default as NavBar } from "./NavBar/NavBar"
^^^^^^

SyntaxError: Unexpected token 'export'
    at wrapSafe (internal/modules/cjs/loader.js:1055:16)
    at Module._compile (internal/modules/cjs/loader.js:1103:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
....

который, кажется, уже встречался ранее в # 2850 и # 883.

Таким образом, похоже, что единственное решение: https://github.com/martpie/next-transpile-modules#but -i-действительно-need-to-make-it-work-with-lerna

Из того, что я слышал, скоро будет представлен RFC, как Next.js планирует решить эту проблему, но если кому-то нужно исправить это прямо сейчас, я опубликовал на npm свое решение с https://github.com/ zeit / next.js / pull / 10098, который вы можете использовать, поместив следующее в package.json:

    "next": "npm:@sheerun/[email protected]",

и следом за next.config.js:

  babelIncludeRegexes: [/turf/],

(в моем случае мне нужно было, чтобы все файлы turf были предварительно скомпилированы с помощью babel)

В этом вопросе есть прогресс?

Я использую next.js 9.2.0, но опция babelIncludeRegexes не работает

В этом вопросе есть прогресс?

next-transpile-modules нацелен именно на решение этой проблемы, вы пробовали?

Привет @martpie!

Уже решаю мою проблему редактированием файла .babelrc. Я ссылаюсь на эту проблему

Спасибо

@martpie Я использую next-transpile-modules но все же я сталкиваюсь с ошибкой ниже, когда пытаюсь создать приложение. Я использую монорепозиторий с общей кодовой базой. Попытка получить доступ к компонентам из общего доступа, например @ myapp / shared / components / componentname.js. Я использую nextjs 9.x и пользовательский next.config.js .

Ошибка
`
Ошибка синтаксического анализа модуля: неожиданный токен (12: 4)
Вам может потребоваться соответствующий загрузчик для обработки этого типа файла, в настоящее время загрузчики не настроены для обработки этого файла. См. Https://webpack.js.org/concepts#loaders.
| const Spinner = props => {
| const renderDefaultSpinner = (spinnerClass, {... другие}) => (
>


| );
|

Произошла ошибка сборки
Ошибка:> Сбой сборки из-за ошибок веб-пакета
`

next.config.js
const withTM = require('next-transpile-modules')(['<strong i="26">@myapp</strong>']); module.exports = withPlugins([withTM, withBundleAnalyzer], { ... }

Пожалуйста, помогите в том, что я здесь делаю неправильно.

@ raghav1086 Можете ли вы открыть вопрос по репо? ;) это позволит избежать шума для людей здесь.

+1

У меня есть каталог src/ для моего проекта и lib/ для начального фреймворка, который экспортирует некоторые общие утилиты / оболочки, которые я повторно использую в нескольких разных приложениях nextjs (моя отправная точка)

lib не замечается, когда я запускаю сервер разработки. любые компоненты из lib / не проходят через загрузчик и выдают ошибку

Я использовал вариант решения @ Lwdthe1 (https://github.com/zeit/next.js/issues/706#issuecomment-569041997), чтобы исправить проблему src и lib в моем комментарии выше. В основном то же самое, за исключением того, что здесь используется config.resolve.modules вместо цикла по массиву aliasPathsToResolve .

  webpack: (config, options) => {
    config.resolve.modules = [
      './src/',
      './lib/',
      'node_modules'
    ];

    config.module.rules.push({
      test: /\.(js|jsx)$/,
      include: [path.resolve(__dirname, './lib/')],
      use: [options.defaultLoaders.babel],
    });

Какое рабочее решение для lerna, nextjs и babel в наши дни?

Я стараюсь избегать предварительной транспиляции моих библиотек перед импортом, и я натолкнулся на кирпичную стену с каждым решением здесь. Вот что у меня не получается:

  • next-transpile-modules .
  • сброс настроек preset-env.
  • обновление правил next-babel-loader include и exclude чтобы они прошли / не прошли соответственно.

@mikestopcontinues next-transpile-modules работал для меня "из коробки" с TypeScript.

@calebmpeterson и @martpie (я вас вижу! 👀). Я вернулся к разъему, и проблема, похоже, в том, что нет возможности ссылаться на подмодули. Например, шаблон «@ mono / components» не поддерживает импорт «@ mono / components / Div» или чего-то еще. И указание '@ mono / components / Div', поскольку шаблон тоже не работает ... не то чтобы я хотел делать это для каждого общего компонента. Я также пробовал реверс-инжиниринг генерации регулярных выражений для создания шаблонов совпадений, и хотя выходное регулярное выражение работает, под капотом происходит кое-что еще, чего нет.

В идеале я просто хотел бы указать '@ mono`, чтобы обо всем позаботиться, и оставил мой package.json единственным источником правды о том, от чего зависит каждое из моих приложений. Точно так же я хотел бы избежать поддержки индексных файлов, которые импортируют / экспортируют все в каждой из моих библиотек, просто чтобы иметь доступ к подмодулям.

Возвращаясь к прошлому, я считаю, что текущая проблема могла бы быть полностью решена, если бы существовал способ передать rootMode: 'upward' через next-babel-loader , чтобы babel мог обрабатывать логику транспилирования. Возможно, это вызывает другие проблемы, связанные с Next, но корень проблемы, похоже, заключается в нетипичном способе запутывания Next в webpack и babel. Конечно, есть способ оставить babel-loader отдельно от дополнительной логики Next?

Просто обновление на фронте next-transpile-modules . Я неправильно диагностировал ошибку. Импорт с использованием этого метода (индекса или подмодуля) не работает, если вам нужен пользовательский .babelrc config. Пользовательские настройки просто не применяются к требуемому коду. Это снова проблема rootMode: 'upward' .

@mikestopcontinues Вам нужно использовать babel.config.js (глобальная конфигурация) с next-transpile-modules , а не .babelrc (локальная конфигурация), это объясняется в FAQ;)

@martpie Ты даже не представляешь, как я смущен. За последние несколько недель мне пришлось прочитать эту строку десятки раз, и я никогда не удосужился перейти к вопросу. Это полностью сработало. Спасибо!

next-transpile-modules сломал для меня React. Теперь он выдает, что я использую недопустимые хуки, в то время как я перенес ТРИ модуля примера

Может ли кто-нибудь повторить, какая конфигурация лучше всего подходит для работы транспиляции. Я не понимаю, что должен написать в babel.config.js

@masbaehr в большинстве случаев просто добавляет next-transpile-modules в настройку next.config

Единственная проблема в том, что next-transpile-modules не поддерживает Yarn 2 pnp.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги