パッケージ、リポジトリ、アプリカテゴリを検索

パッケージ詳細v2.1.0

shelf_modular

依存関係の注入とルート管理を備えたスマートなプロジェクト構造

AndroidiOSWebmacOSWindowsLinux
30日間ダウンロード
137
いいね数
34
Pub ポイント
135

パッケージをインストール

flutter pub add shelf_modular

パッケージ概要

公開情報に基づく選定ガイドです。参考としてご利用ください。

Shelf Modular は、組み込みの依存関係注入とルート管理を備えたスマートなプロジェクト構造を提供するFlutterパッケージです。コードをモジュール化されたコンポーネントに整理することで、アプリアーキテクチャを簡素化し、大規模なアプリケーションのスケーラビリティとメンテナンス性を高めます。Android、iOS、Web、macOS、Windows、Linuxなど、複数プラットフォーム間でのシームレスなナビゲーションをサポートしています。明確な責任の分離を重視し、自動的な依存関係解決と直感的なルーティングにより、開発者の生産性を向上させます。

用途

  • 大規模なFlutterアプリケーション
  • モジュラーアプリケーションアーキテクチャ
  • クロスプラットフォーム開発
  • 依存性の注入
  • ダイナミックルート処理

主な機能

  • 組み込みの依存関係の挿入
  • モジュール式ルーティングシステム
  • プラットフォームに依存しない設計
  • コード組織のベストプラクティス
  • 自動モジュール読み込み

適している対象

  • 経験豊富なFlutter開発者
  • 複雑なアプリを構築するチーム
  • スケーラビリティを必要とするプロジェクト

注意事項

  • 初心者にとって学習曲線が急峻
  • モジュール構造の遵守が必要です
  • 主流パッケージと比べてドキュメントが限られている

元の README

関連するソースリポジトリの README 原文のスナップショットです。最新の内容はリポジトリをご覧ください。


Modular

Flutter Modular

A smart, modular project structure
Route management, dependency injection and scoped state — organized by feature, the Flutter way.

flutter_modular v7 pub version license

Documentation · Report Bug · Request Feature

Maintained by Flutterando



Table of Contents
  1. About The Project
    1. What is Modular?
    2. Ready to get started?
    3. Common questions
  2. Usage
    1. Install
    2. Declare a module
    3. Bootstrap with ModularApp
    4. Navigate
    5. Page-scoped state
  3. Contributing
  4. Contact
  5. Contributors


:memo: About The Project

Let's find out how to implement a Modular structure in your project.

What is Modular?

Modular proposes to solve two problems:

  • Modularized routes.
  • Modularized Dependency Injection.

In a monolithic architecture, where we have our entire application as a single module, we design our software in a quick and elegant way, taking advantage of all the amazing features of Flutter💙. However, producing a larger app in a "monolithic" way can generate technical debt in both maintanance and scalability. With this in mind, developers adopted architectural strategies to better divide the code, minimizing the negative impacts on the project's maintainability and scalability..

By better dividing the scope of features, we gain:

  • Improved understanding of features.
  • Less breaking changes.
  • Add new non-conflicting features.
  • Less blind spots in the project's main business rule.
  • Improved developer turnover.

With a more readable code, we extend the life of the project. See example of a standard MVC with 3 features(Auth, Home, Product):

A typical MVC
.
├── models                                  # All models      
│   ├── auth_model.dart                     
│   ├── home_model.dart                     
│   └── product_model.dart         
├── controller                              # All controllers
│   ├── auth_controller.dart                     
│   ├── home_controller.dart                     
│   └── product_controller.dart             
├── views                                   # All views
│   ├── auth_page.dart                     
│   ├── home_page.dart                     
│   └── product_page.dart                   
├── core                                    # Tools and utilities
├── app_widget.dart                         # Main Widget containing MaterialApp 
└── main.dart                               # runApp 

Here we have a default structure using MVC. This is incredibly useful in almost every application.

Let's see how the structure looks when we divide by scope:

Structure divided by scope
.                  
├── features                                 # All features or Modules 
│   ├─ auth                                  # Auth's MVC       
│   │  ├── auth_model.dart   
│   │  ├── auth_controller.dart  
│   │  └── auth_page.dart                      
│   ├─ home                                  # Home's MVC       
│   │  ├── home_model.dart   
│   │  ├── home_controller.dart  
│   │  └── home_page.dart                        
│   └─ product                               # Product's MVC     
│      ├── product_model.dart   
│      ├── product_controller.dart
│      └── product_page.dart                    
├── core                                     # Tools and utilities
├── app_widget.dart                          # Main Widget containing MaterialApp 
└── main.dart                                # runApp 

What we did in this structure was to continue using MVC, but this time in scope. This means that each feature has its own MVC, and this simple approach solves many scalability and maintainability issues. We call this approach "Smart Structure". But two things were still Global and clashed with the structure itself, so we created Modular to solve this impasse.

In short: Modular is a solution to modularize the route and dependency injection system, making each scope have its own routes and injections independent of any other factor in the structure. We create objects to group the Routes and Injections and call them Modules.

Ready to get started?

Modular is not only ingenious for doing something amazing like componentizing Routes and Dependency Injections, it's amazing for being able to do all this simply!

Go to the next topic and start your journey towards an intelligent structure.

Common questions

  • Does Modular work with any state management approach?

    • Yes, the dependency injection system is agnostic to any kind of class including the reactivity that makes up state management.
  • Can I use dynamic routes?

    • Yes! The entire route tree responds as on the Web. You can use dynamic :params, query strings, relative paths, nested routes and persistent shells (RouterOutlet). Use a route guard to redirect (e.g. to a 404 or a login page).
  • Do I need to create a Module for all features?

    • No. You can create a module only when you think it's necessary or when the feature is no longer a part of the scope in which it is being worked on.

✨ Usage

flutter_modular 7 is a ground-up rewrite. A Module is now exactly the two things that couple a Flutter app — Dependency Injection + Routes — declared with a small functional API. State is page-scoped, tied to the route lifecycle, so ownership and disposal stop being your problem and the durable truth lives in a repository/service registered in DI. Full, runnable demonstrations (nested routes, RouterOutlet shells, route guards, per-module DI lifecycle, arguments/pop-results) live in example/.

Install
dependencies:
  flutter_modular: ^7.0.0

or run flutter pub add flutter_modular.

Declare a module

A module groups routes and dependency injection. Shared dependencies are registered with addSingleton/add*, routes with route(...), and submodules with module(...).

import 'package:flutter_modular/flutter_modular.dart';

final appModule = createModule(register: (c) {
  c
    ..addSingleton<Counter>(Counter.new)                       // shared dependency (SSoT)
    ..route('/', child: (ctx, state) => const HomePage())
    ..route('/details/:id',
        child: (ctx, state) => DetailsPage(id: state.params['id']!));
});
Bootstrap with ModularApp

ModularApp is the first widget, above MaterialApp. It bootstraps the module, owns the injector, and exposes the router config.

void main() => runApp(
      ModularApp(module: appModule, child: const AppRoot()),
    );

class AppRoot extends StatelessWidget {
  const AppRoot({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routerConfig: ModularApp.routerConfigOf(context),
      );
}
Navigate
context.pushNamed('/details/42'); // stacks a page (push stays out of the URL)
context.navigate('/');            // replaces the stack (owns the URL, resets history)
context.pop(result);              // pops, delivering a result to the awaiting pushNamed
Page-scoped state

State lives 1:1 with a view via provide — built in a page-local scope and disposed when the route leaves, so there are no floating globals and no manual dispose.

c.route('/counter',
  provide: (s) => s.addChangeNotifier<CounterViewModel>(CounterViewModel.new),
  child: (ctx, state) => const CounterPage(),
);

// inside the page:
final vm = context.watch<CounterViewModel>(); // rebuilds when the VM notifies

// granular: rebuild only when the selected value changes (provider-style)
final count = context.select<CounterViewModel, int>((vm) => vm.count);

🧑‍💻 Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the appropriate tag. Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Remember to include a tag, and to follow Conventional Commits and Semantic Versioning when uploading your commit and/or creating the issue.

(back to top)

💬 Contact

Flutterando Community

(back to top)


👥 Contributors

(back to top)

🛠️ Maintaned by


This fork version is maintained by Flutterando.

カテゴリー

依存関係

依存関係一覧 7 件

ソースリポジトリ

このパッケージを使用しているプロジェクト

データはまだありません。