Skip to content

Instantly share code, notes, and snippets.

@nandorojo
Last active July 23, 2021 13:25
Show Gist options
  • Select an option

  • Save nandorojo/76d451552d6732e6ddebb74be12af833 to your computer and use it in GitHub Desktop.

Select an option

Save nandorojo/76d451552d6732e6ddebb74be12af833 to your computer and use it in GitHub Desktop.
Expo + Next.js + Webpack 5

Here are my attempts to use webpack 5 with Expo's Next.js integration.

Next v10.2 uses webpack5 by default. However, this breaks @expo/next-adapater.

Relevant PR

In order to test / reproduce this, I added this PR to my Expo + Next.js monorepo starter: nandorojo/expo-next-monorepo#1

HTML Webpack Plugin

First, an error occurs with html-webpack-plugin, where it says it cannot find version of undefined. html-webpack-plugin is a dependency of @expo/webpack-config.

The solution is to use html-webpack-plugin v5. I added this to my package.json:

{
  "resolutions": {
    "html-webpack-plugin": "5.3.1"
   }
}

Then ran yarn install and that solved it (won't work with npm).

Webpack Schema

Then I ran yarn next, and got this error:

ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema
Click to see full error
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
warn  - React 17.0.1 or newer will be required to leverage all of the upcoming features in Next.js 11. Read more: https://nextjs.org/docs/messages/react-version
info  - Using webpack 5. Reason: future.webpack5 option enabled https://nextjs.org/docs/messages/webpack5
ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
 - configuration[0].module.rules[7] should be one of these:
   ["..." | object { compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?, loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?, resource?, resourceFragment?, resourceQuery?, rules?, sideEffects?, test?, type?, use? }, ...]
   -> A rule.
   Details:
    * configuration[0].module.rules[7].loader should be a non-empty string.
      -> A loader request.
 - configuration[1].module.rules[7] should be one of these:
   ["..." | object { compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?, loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?, resource?, resourceFragment?, resourceQuery?, rules?, sideEffects?, test?, type?, use? }, ...]
   -> A rule.
   Details:
    * configuration[1].module.rules[7].loader should be a non-empty string.
      -> A loader request.
    at validate (/path/to/app/node_modules/next/dist/compiled/schema-utils3/index.js:1:153657)
    at validateSchema (/path/to/app/node_modules/next/dist/compiled/webpack/bundle5.js:134010:2)
    at create (/path/to/app/node_modules/next/dist/compiled/webpack/bundle5.js:137441:24)
    at webpack (/path/to/app/node_modules/next/dist/compiled/webpack/bundle5.js:137479:32)
    at f (/path/to/app/node_modules/next/dist/compiled/webpack/bundle5.js:95234:15)
    at HotReloader.start (/path/to/app/node_modules/next/dist/server/hot-reloader.js:18:415)
    at async DevServer.prepare (/path/to/app/node_modules/next/dist/server/next-dev-server.js:16:453)
    at async /path/to/app/node_modules/next/dist/cli/next-dev.js:22:1 {
  errors: [
    {
      keyword: 'oneOf',
      dataPath: '[0].module.rules',
      schemaPath: '#/properties/rules/oneOf',
      params: [Object],
      message: 'should match exactly one schema in oneOf',
      schema: [Array],
      parentSchema: [Object],
      data: [Array],
      children: [Array]
    },
    {
      keyword: 'oneOf',
      dataPath: '[1].module.rules',
      schemaPath: '#/properties/rules/oneOf',
      params: [Object],
      message: 'should match exactly one schema in oneOf',
      schema: [Array],
      parentSchema: [Object],
      data: [Array],
      children: [Array]
    }
  ],
  schema: {
    definitions: {
      Amd: [Object],
      AssetFilterItemTypes: [Object],
      AssetFilterTypes: [Object],
      AssetGeneratorDataUrl: [Object],
      AssetGeneratorDataUrlFunction: [Object],
      AssetGeneratorDataUrlOptions: [Object],
      AssetGeneratorOptions: [Object],
      AssetInlineGeneratorOptions: [Object],
      AssetModuleFilename: [Object],
      AssetParserDataUrlFunction: [Object],
      AssetParserDataUrlOptions: [Object],
      AssetParserOptions: [Object],
      AssetResourceGeneratorOptions: [Object],
      AuxiliaryComment: [Object],
      Bail: [Object],
      CacheOptions: [Object],
      CacheOptionsNormalized: [Object],
      Charset: [Object],
      ChunkFilename: [Object],
      ChunkFormat: [Object],
      ChunkLoadTimeout: [Object],
      ChunkLoading: [Object],
      ChunkLoadingGlobal: [Object],
      ChunkLoadingType: [Object],
      Clean: [Object],
      CleanOptions: [Object],
      CompareBeforeEmit: [Object],
      Context: [Object],
      CrossOriginLoading: [Object],
      Dependencies: [Object],
      DevServer: [Object],
      DevTool: [Object],
      DevtoolFallbackModuleFilenameTemplate: [Object],
      DevtoolModuleFilenameTemplate: [Object],
      DevtoolNamespace: [Object],
      EmptyGeneratorOptions: [Object],
      EmptyParserOptions: [Object],
      EnabledChunkLoadingTypes: [Object],
      EnabledLibraryTypes: [Object],
      EnabledWasmLoadingTypes: [Object],
      Entry: [Object],
      EntryDescription: [Object],
      EntryDescriptionNormalized: [Object],
      EntryDynamic: [Object],
      EntryDynamicNormalized: [Object],
      EntryFilename: [Object],
      EntryItem: [Object],
      EntryNormalized: [Object],
      EntryObject: [Object],
      EntryRuntime: [Object],
      EntryStatic: [Object],
      EntryStaticNormalized: [Object],
      EntryUnnamed: [Object],
      Environment: [Object],
      Experiments: [Object],
      ExternalItem: [Object],
      ExternalItemFunctionData: [Object],
      ExternalItemValue: [Object],
      Externals: [Object],
      ExternalsPresets: [Object],
      ExternalsType: [Object],
      FileCacheOptions: [Object],
      Filename: [Object],
      FilenameTemplate: [Object],
      FilterItemTypes: [Object],
      FilterTypes: [Object],
      GeneratorOptionsByModuleType: [Object],
      GlobalObject: [Object],
      HashDigest: [Object],
      HashDigestLength: [Object],
      HashFunction: [Object],
      HashSalt: [Object],
      HotUpdateChunkFilename: [Object],
      HotUpdateGlobal: [Object],
      HotUpdateMainFilename: [Object],
      IgnoreWarnings: [Object],
      IgnoreWarningsNormalized: [Object],
      Iife: [Object],
      ImportFunctionName: [Object],
      ImportMetaName: [Object],
      InfrastructureLogging: [Object],
      JavascriptParserOptions: [Object],
      Layer: [Object],
      Library: [Object],
      LibraryCustomUmdCommentObject: [Object],
      LibraryCustomUmdObject: [Object],
      LibraryExport: [Object],
      LibraryName: [Object],
      LibraryOptions: [Object],
      LibraryType: [Object],
      Loader: [Object],
      MemoryCacheOptions: [Object],
      Mode: [Object],
      ModuleFilterItemTypes: [Object],
      ModuleFilterTypes: [Object],
      ModuleOptions: [Object],
      ModuleOptionsNormalized: [Object],
      Name: [Object],
      NoParse: [Object],
      Node: [Object],
      NodeOptions: [Object],
      Optimization: [Object],
      OptimizationRuntimeChunk: [Object],
      OptimizationRuntimeChunkNormalized: [Object],
      OptimizationSplitChunksCacheGroup: [Object],
      OptimizationSplitChunksGetCacheGroups: [Object],
      OptimizationSplitChunksOptions: [Object],
      OptimizationSplitChunksSizes: [Object],
      Output: [Object],
      OutputModule: [Object],
      OutputNormalized: [Object],
      Parallelism: [Object],
      ParserOptionsByModuleType: [Object],
      Path: [Object],
      Pathinfo: [Object],
      Performance: [Object],
      PerformanceOptions: [Object],
      Plugins: [Object],
      Profile: [Object],
      PublicPath: [Object],
      RawPublicPath: [Object],
      RecordsInputPath: [Object],
      RecordsOutputPath: [Object],
      RecordsPath: [Object],
      Resolve: [Object],
      ResolveAlias: [Object],
      ResolveLoader: [Object],
      ResolveOptions: [Object],
      ResolvePluginInstance: [Object],
      RuleSetCondition: [Object],
      RuleSetConditionAbsolute: [Object],
      RuleSetConditionOrConditions: [Object],
      RuleSetConditionOrConditionsAbsolute: [Object],
      RuleSetConditions: [Object],
      RuleSetConditionsAbsolute: [Object],
      RuleSetLoader: [Object],
      RuleSetLoaderOptions: [Object],
      RuleSetRule: [Object],
      RuleSetRules: [Object],
      RuleSetUse: [Object],
      RuleSetUseItem: [Object],
      ScriptType: [Object],
      SnapshotOptions: [Object],
      SourceMapFilename: [Object],
      SourcePrefix: [Object],
      StatsOptions: [Object],
      StatsValue: [Object],
      StrictModuleErrorHandling: [Object],
      StrictModuleExceptionHandling: [Object],
      Target: [Object],
      UmdNamedDefine: [Object],
      UniqueName: [Object],
      WarningFilterItemTypes: [Object],
      WarningFilterTypes: [Object],
      WasmLoading: [Object],
      WasmLoadingType: [Object],
      Watch: [Object],
      WatchOptions: [Object],
      WebassemblyModuleFilename: [Object],
      WebpackOptionsNormalized: [Object],
      WebpackPluginFunction: [Object],
      WebpackPluginInstance: [Object]
    },
    title: 'WebpackOptions',
    description: 'Options object as provided by the user.',
    type: 'object',
    additionalProperties: false,
    properties: {
      amd: [Object],
      bail: [Object],
      cache: [Object],
      context: [Object],
      dependencies: [Object],
      devServer: [Object],
      devtool: [Object],
      entry: [Object],
      experiments: [Object],
      externals: [Object],
      externalsPresets: [Object],
      externalsType: [Object],
      ignoreWarnings: [Object],
      infrastructureLogging: [Object],
      loader: [Object],
      mode: [Object],
      module: [Object],
      name: [Object],
      node: [Object],
      optimization: [Object],
      output: [Object],
      parallelism: [Object],
      performance: [Object],
      plugins: [Object],
      profile: [Object],
      recordsInputPath: [Object],
      recordsOutputPath: [Object],
      recordsPath: [Object],
      resolve: [Object],
      resolveLoader: [Object],
      snapshot: [Object],
      stats: [Object],
      target: [Object],
      watch: [Object],
      watchOptions: [Object]
    }
  },
  headerName: 'Webpack',
  baseDataPath: 'configuration',
  postFormatter: [Function: postFormatter]
}
@nandorojo
Copy link
Author

Hey there’s a more official issue for this on the Expo repo now. They upgraded expo next adapter to v3 to support next 11 and Webpack 5.

@nandorojo
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment