Saltar al contenido principal

Convenciones de estructura de paquetes

Aprende más sobre la estructura de directorios utilizada por la herramienta de gestión de paquetes de Dart, pub.

Cuando compilas un paquete de pub package, te animamos a seguir las convenciones que describe esta página. Describen cómo organizas los archivos y directorios dentro de tu paquete, y cómo nombrar las cosas.

Así es como podría verse un paquete completo (llamado enchilada) que utiliza todos los aspectos de estas pautas:

  • enchilada/
    • .dart_tool/*
    • benchmark/
      • make_lunch.dart
    • bin/
      • enchilada
    • doc/
      • api/****
      • getting_started.md
    • example/
      • main.dart
    • hook/
      • build.dart
    • integration_test/
      • app_test.dart
    • lib/
      • enchilada.dart
      • tortilla.dart
      • guacamole.css
      • src/
        • beans.dart
        • queso.dart
    • test/
      • enchilada_test.dart
      • tortilla_test.dart
    • tool/
      • generate_docs.dart
    • web/
      • index.html
      • main.dart
      • style.css
    • CHANGELOG.md
    • LICENSE
    • pubspec.yaml
    • pubspec_overrides.yaml**
    • pubspec.lock***
    • README.md

* El directorio .dart_tool/ existe después de haber ejecutado dart pub get. No lo registres en el control de código fuente. Para obtener más información, consulta Caché específica del proyecto para herramientas.

** El archivo pubspec_overrides.yaml, si está presente, anula ciertos aspectos de pubspec.yaml. Por lo general, no querrás registrarlo en el control de código fuente.

*** El archivo pubspec.lock existe después de haber ejecutado dart pub get. Déjalo fuera del control de código fuente a menos que tu paquete sea un paquete de aplicación (application package)Paquete de aplicaciónUn paquete de Dart que contiene una aplicación ejecutable. Obtén más información.

**** El directorio doc/api existe localmente después de haber ejecutado dart doc. No registres el directorio api en el control de código fuente.

El pubspec

#
  • enchilada/
    • pubspec.yaml
    • pubspec.lock

Cada paquete tiene un pubspec, un archivo llamado pubspec.yaml, en el directorio raíz del paquete. Eso es lo que lo convierte en un paquete.

Ejecutar dart pub get, dart pub upgrade o dart pub downgrade en el paquete crea un archivo de bloqueo (lockfile), llamado pubspec.lock. Si tu paquete es un paquete de aplicación (application package)Paquete de aplicaciónUn paquete de Dart que contiene una aplicación ejecutable. Obtén más información, registra el archivo de bloqueo en el control de código fuente. De lo contrario, no lo hagas.

Para obtener más información, consulta la página del pubspec.

LICENSE

#
  • enchilada/
    • LICENSE

Si vas a publicar tu paquete, incluye un archivo de licencia llamado LICENSE. Recomendamos usar una licencia aprobada por la OSI como BSD-3-Clause, para que otros puedan reutilizar tu trabajo.

README.md

#
  • enchilada/
    • README.md

Un archivo muy común en el código abierto es un archivo README que describe el proyecto. Esto es especialmente importante en pub. Cuando lo cargas en el sitio pub.dev, se muestra tu archivo README.md (renderizado como Markdown) en la página de tu paquete. Este es el lugar perfecto para presentar tu código a las personas.

Para obtener orientación sobre cómo escribir un excelente README, consulta Cómo escribir páginas de paquetes (Writing package pages).

CHANGELOG.md

#
  • enchilada/
    • CHANGELOG.md

Incluye un archivo CHANGELOG.md que tenga una sección para cada versión de tu paquete, con notas para ayudar a los usuarios de tu paquete a actualizar. Los usuarios de tu paquete a menudo revisan el registro de cambios (changelog) para descubrir correcciones de errores y nuevas características, o para determinar cuánto esfuerzo requerirá actualizar a la última versión de tu paquete.

Para dar soporte a las herramientas que analizan CHANGELOG.md, utiliza el siguiente formato:

  • Cada versión tiene su propia sección con un encabezado.
  • Los encabezados de versión son todos de nivel 1 o todos de nivel 2.
  • El texto del encabezado de la versión contiene un número de versión del paquete, opcionalmente precedido por "v".

Cuando cargas tu paquete en el sitio pub.dev, el archivo CHANGELOG.md de tu paquete (si existe) aparece en la pestaña Changelog, renderizado como Markdown.

Aquí hay un ejemplo de un archivo CHANGELOG.md. Como muestra el ejemplo, puedes agregar subsecciones.

markdown
# 1.0.1

* Fixed missing exclamation mark in `sayHi()` method.

# 1.0.0

* **Breaking change:** Removed deprecated `sayHello()` method.
* Initial stable release.

## Upgrading from 0.1.x

Change all calls to `sayHello()` to instead be to `sayHi()`.

# 0.1.1

* Deprecated the `sayHello()` method; use `sayHi()` instead.

# 0.1.0

* Initial development release.

Directorios públicos

#

Dos directorios en tu paquete son públicos para otros paquetes: lib y bin. Colocas las bibliotecas públicas en lib y las herramientas públicas en bin.

Bibliotecas públicas

#

La siguiente estructura de directorios muestra la parte lib de enchilada:

  • enchilada/
    • lib/
      • enchilada.dart
      • tortilla.dart

Muchos paquetesPaqueteUn directorio con una colección de bibliotecas de Dart, recursos, y un archivo pubspec.yaml que los describe. Obtén más información definen bibliotecas de Dart que otros paquetes pueden importar y usar. Estos archivos públicos de biblioteca de Dart van dentro de un directorio llamado lib.

La mayoría de los paquetes definen una única biblioteca que los usuarios pueden importar. En ese caso, su nombre generalmente debería ser el mismo que el nombre del paquete, como enchilada.dart en el ejemplo aquí. Pero también puedes definir otras bibliotecas con los nombres que tengan sentido para tu paquete.

Cuando lo haces, los usuarios pueden importar estas bibliotecas usando el nombre del paquete y del archivo de biblioteca, de la siguiente manera:

dart
import 'package:enchilada/enchilada.dart';
import 'package:enchilada/tortilla.dart';

Si deseas organizar tus bibliotecas públicas, también puedes crear subdirectorios dentro de lib. Si haces eso, los usuarios especificarán esa ruta cuando la importen. Supongamos que tienes la siguiente jerarquía de archivos:

  • enchilada/
    • lib/
      • some/
        • path/
          • olives.dart

Los usuarios importan olives.dart de la siguiente manera:

dart
import 'package:enchilada/some/path/olives.dart';

Ten en cuenta que solo las bibliotecas deben estar en lib. Los puntos de entrada (entrypoints), que son scripts de Dart con una función main(), no pueden ir en lib. Si colocas un script de Dart dentro de lib, descubrirás que las importaciones package: que contenga no se resolverán. En su lugar, tus puntos de entrada deben ir en el directorio de puntos de entrada (entrypoint directory)Directorio de puntos de entradaUn directorio que contiene puntos de entrada de Dart. Obtén más información apropiado.

Para obtener más información sobre los paquetes, consulta Cómo crear paquetes (Creating packages).

Herramientas públicas

#

Los scripts de Dart colocados dentro del directorio bin son públicos. Si estás dentro del directorio de un paquete, puedes usar dart run para ejecutar scripts desde los directorios bin de cualquier otro paquete del que dependa el paquete. Desde cualquier directorio, puedes ejecutar scripts de paquetes que hayas activado utilizando dart pub global activate.

Si tienes la intención de que se dependa de tu paquete, y deseas que tus scripts sean privados para tu paquete, colócalos en el directorio tool de nivel superior. Si no tienes la intención de que se dependa de tu paquete, puedes dejar tus scripts en bin.

Activos (assets) públicos

#
  • enchilada/
    • lib/
      • guacamole.css

Aunque la mayoría de los paquetes existen para permitirte reutilizar código de Dart, también puedes reutilizar otros tipos de contenido. Por ejemplo, un paquete para Bootstrap podría incluir varios archivos CSS para que los utilicen los consumidores del paquete.

Estos van en el directorio lib de nivel superior. Puedes poner cualquier tipo de archivo allí y organizarlo con subdirectorios como quieras.

Archivos de implementación

#
  • enchilada/
    • lib/
      • src/
        • beans.dart
        • queso.dart

Las bibliotecas dentro de lib son públicamente visibles: otros paquetes son libres de importarlas. Pero gran parte del código de un paquete son bibliotecas de implementación interna que solo deben ser importadas y utilizadas por el propio paquete. Esas van dentro de un subdirectorio de lib llamado src. Puedes crear subdirectorios allí si te ayuda a organizar las cosas.

Eres libre de importar bibliotecas que vivan en lib/src desde otro código de Dart en el mismo paquete (como otras bibliotecas en lib, scripts en bin y pruebas), pero nunca deberías importar desde el directorio lib/src de otro paquete. Esos archivos no son parte de la API pública del paquete y podrían cambiar de formas que podrían romper tu código.

La forma en que importas bibliotecas desde tu propio paquete depende de las ubicaciones de las bibliotecas:

Por ejemplo:

lib/beans.dart
dart
// When importing from within lib:
import 'src/beans.dart';
test/beans_test.dart
dart
// When importing from outside lib:
import 'package:enchilada/src/beans.dart';

El nombre que usas aquí (en este caso enchilada) es el nombre que especificas para tu paquete en su pubspec.

Archivos web

#
  • enchilada/
    • web/
      • index.html
      • main.dart
      • style.css

Para los paquetes web, coloca el código del punto de entrada (entrypoint) —scripts de Dart que incluyan main() y archivos de soporte, como CSS o HTML— bajo web. Puedes organizar el directorio web en subdirectorios si lo deseas.

Coloca el código de la biblioteca (library code) bajo lib. Si la biblioteca no es importada directamente por el código bajo web, o por otro paquete, colócala bajo lib/src. Coloca los ejemplos basados en web bajo example. Consulta Activos públicos para obtener consejos sobre dónde colocar los activos, como las imágenes.

Aplicaciones de línea de comandos

#
  • enchilada/
    • bin/
      • enchilada

Algunos paquetes definen programas que se pueden ejecutar directamente desde la línea de comandos. Estos pueden ser scripts de shell o cualquier otro lenguaje de scripting, incluido Dart.

Si tu paquete define código como este, colócalo en un directorio llamado bin. Puedes ejecutar ese script desde cualquier lugar de la línea de comandos, si lo configuras utilizando dart pub global.

Pruebas y pruebas de rendimiento (benchmarks)

#
  • enchilada/
    • test/
      • enchilada_test.dart
      • tortilla_test.dart

Cada paquete debería tener pruebas. Con pub, la convención es que la mayoría de estas vayan en un directorio test (o en algún directorio dentro de él, si lo deseas) y tengan _test al final de sus nombres de archivo.

Normalmente, estas utilizan el paquete test.

  • enchilada/
    • integration_test/
      • app_test.dart

Los paquetes de apps de Flutter también pueden tener pruebas de integración especiales, las cuales usan el paquete integration_test. Estas pruebas viven en su propio directorio integration_test.

Otros paquetes pueden optar por seguir un patrón similar para separar sus pruebas de integración más lentas de sus pruebas unitarias, pero ten en cuenta que por defecto dart test no ejecutará estas pruebas. Tendrás que ejecutarlas explícitamente con dart test integration_test.

  • enchilada/
    • benchmark/
      • make_lunch.dart

Los paquetes que tienen código de rendimiento crítico también pueden incluir pruebas de rendimiento (benchmarks). Estas prueban la API no para verificar su corrección, sino su velocidad (o el uso de memoria, o tal vez otras métricas empíricas).

Documentación

#
  • enchilada/
    • doc/
      • api/
      • getting_started.md

Si tienes código y pruebas, la siguiente pieza que podrías desear es una buena documentación. Eso va dentro de un directorio llamado doc.

Cuando ejecutas la herramienta dart doc, esta coloca la documentación de la API, por defecto, bajo doc/api. Dado que la documentación de la API se genera a partir del código fuente, no debes colocarla bajo el control de versiones.

Aparte de la api generada, no tenemos pautas sobre el formato o la organización de la documentación que escribas. Usa el formato de marcado que prefieras.

Ejemplos

#
  • enchilada/
    • example/
      • main.dart

Código, pruebas, documentos, ¿qué más podrían desear tus usuarios? ¡Programas de ejemplo independientes que utilicen tu paquete, por supuesto! Esos van dentro del directorio example. Si los ejemplos son complejos y utilizan múltiples archivos, considera crear un directorio para cada ejemplo. De lo contrario, puedes colocar cada uno directamente dentro de example.

En tus ejemplos, usa package: para importar archivos de tu propio paquete. Esto garantiza que el código de ejemplo en tu paquete se vea exactamente igual a como se vería el código fuera de tu paquete.

Si vas a publicar tu paquete, considera crear un archivo de ejemplo con uno de los siguientes nombres:

  • example/example[.md]
  • example[/lib]/main.dart
  • example[/lib]/package_name.dart
  • example[/lib]/package_name_example.dart
  • example[/lib]/example.dart
  • example/README[.md]

Cuando publicas un paquete que contiene uno o más de los archivos anteriores, el sitio pub.dev crea una pestaña Example para mostrar el primer archivo que encuentre (buscando en el orden que se muestra en la lista anterior). Por ejemplo, si tu paquete tiene muchos archivos bajo su directorio example, incluido un archivo llamado README.md, entonces la pestaña Example de tu paquete muestra el contenido de example/README.md (analizado como Markdown).

Herramientas y scripts internos

#
  • enchilada/
    • tool/
      • generate_docs.dart

Los paquetes maduros a menudo tienen pequeños scripts y programas auxiliares que las personas ejecutan mientras desarrollan el propio paquete. Piensa en cosas como ejecutores de pruebas (test runners), generadores de documentación u otros elementos de automatización.

A diferencia de los scripts en bin, estos no son para usuarios externos del paquete. Si tienes alguno de estos, colócalos en un directorio llamado tool.

Hooks

#
  • enchilada/
    • hook/
      • build.dart

Los paquetes pueden definir ganchos (hooks) para ser invocados por el SDK de Dart y Flutter. Estos ganchos tienen una CLI predefinida y serán invocados por las herramientas del SDK si están presentes.

Debido a que estos ganchos (hooks) son invocados por las herramientas dart y flutter en ejecuciones y compilaciones, las dependencias de estos ganchos deben ser dependencias normales y no dev_dependencies.

Para obtener más información sobre cómo definir ganchos, consulta la documentación de build hooks.

Caché específica del proyecto para herramientas

#

El directorio .dart_tool/ se crea cuando ejecutas dart pub get y puede eliminarse en cualquier momento. Varias herramientas utilizan este directorio para almacenar en caché archivos específicos de tu proyecto y/o máquina local. El directorio .dart_tool/ nunca debe registrarse en el control de versiones, ni copiarse entre máquinas.

También suele ser seguro eliminar el directorio .dart_tool/, aunque es posible que algunas herramientas necesiten volver a calcular la información almacenada en caché.

Ejemplo: La herramienta dart pub get descargará y extraerá las dependencias en un directorio global $PUB_CACHE, y luego escribirá un archivo .dart_tool/package_config.json que asigna los nombres de los paquetes a directorios en el directorio global $PUB_CACHE. El archivo .dart_tool/package_config.json es utilizado por otras herramientas, como el analyzer y los compiladores, cuando necesitan resolver declaraciones como import 'package:foo/foo.dart'.

Al desarrollar una herramienta que necesita almacenamiento en caché específico del proyecto, podrías considerar el uso del directorio .dart_tool/ porque la mayoría de los usuarios ya lo ignoran con .gitignore. Al almacenar archivos en caché para tu herramienta en el directorio .dart_tool/ de un usuario, debes usar un subdirectorio único. Para evitar colisiones, los subdirectorios con la forma .dart_tool/<tool_package_name>/ están reservados para el paquete llamado <tool_package_name>. Si tu herramienta no se distribuye a través del sitio pub.dev, podrías considerar publicar un paquete de marcador de posición (placeholder) para reservar el nombre único.

Ejemplo: package:build proporciona un framework para escribir pasos de generación de código. Al ejecutar estos pasos de compilación, los archivos se almacenan en caché en .dart_tool/build/. Esto ayuda a acelerar futuras ejecuciones de los pasos de compilación.