Cách sử dụng Bootstrap 4 trong ASP.NET Core


112

Tôi muốn cập nhật Bootstrap trong ASP.NET Core với NuGet. Tôi đã sử dụng cái này:

Install-Package bootstrap -Version 4.0.0

Nó đã thêm các phụ thuộc nhưng làm cách nào để thêm nó vào dự án của tôi bây giờ? Đường dẫn cho các phụ thuộc NuGet cục bộ là gì?

Các phụ thuộc NuGet đã cài đặt


3
BS4 không nên có hỗ trợ Bower (nguồn: getbootstrap.com/docs/4.0/migration/#breaking )
Klooven

Thay thế bootstrap@4.0.0-beta.3 bằng bootstrap@4.0.0: stackoverflow.com/questions/47985337/…
mrapi

1
Hiện nay đây sẽ là câu trả lời được chấp nhận, dễ sử dụng Libman: stackoverflow.com/a/53012140/578552
rfcdejong

Phiên bản 4.4.1 hiện tương thích bởi NUGET.
Diego Venâncio

Câu trả lời:


223

Như những người khác đã đề cập, trình quản lý gói Bower , thường được sử dụng cho các phần phụ thuộc như thế này trong ứng dụng không dựa vào kịch bản phía máy khách nặng, đang trên đường ra mắt và tích cực đề xuất chuyển sang các giải pháp khác:

..sst! Trong khi Bower được bảo trì, chúng tôi khuyên bạn nên sử dụng sợiwebpack cho các dự án front-end mới!

Vì vậy, mặc dù bạn vẫn có thể sử dụng nó ngay bây giờ, Bootstrap cũng đã thông báo ngừng hỗ trợ cho nó . Do đó, các mẫu ASP.NET Core tích hợp sẵn đang dần được chỉnh sửa để loại bỏ nó.

Thật không may, không có con đường rõ ràng về phía trước. Điều này chủ yếu là do các ứng dụng web liên tục tiến sâu hơn vào phía máy khách, đòi hỏi hệ thống xây dựng phía máy khách phức tạp và nhiều phụ thuộc. Vì vậy, nếu bạn đang xây dựng một cái gì đó như vậy, bạn có thể đã biết cách giải quyết vấn đề này sau đó và bạn có thể mở rộng quy trình xây dựng hiện tại của mình để chỉ cần bao gồm Bootstrap và jQuery ở đó.

Nhưng vẫn còn nhiều ứng dụng web ngoài kia không quá nặng về phía máy khách, nơi ứng dụng vẫn chạy chủ yếu trên máy chủ và do đó máy chủ phục vụ các chế độ xem tĩnh. Bower trước đây đã giải quyết vấn đề này bằng cách giúp bạn dễ dàng xuất bản các phụ thuộc phía máy khách mà không cần nhiều quá trình.

Trong thế giới .NET, chúng tôi cũng có NuGet và với các phiên bản ASP.NET trước đó, chúng tôi cũng có thể sử dụng NuGet để thêm các phụ thuộc vào một số phụ thuộc phía máy khách vì NuGet sẽ chỉ đặt nội dung vào dự án của chúng tôi một cách chính xác. Thật không may, với .csprojđịnh dạng mới và NuGet mới, các gói đã cài đặt nằm bên ngoài dự án của chúng tôi, vì vậy chúng tôi không thể đơn giản tham chiếu các gói đó.

Điều này để lại cho chúng tôi một số tùy chọn về cách thêm các phụ thuộc của chúng tôi:

Cài đặt một lần

Đây là những gì các mẫu ASP.NET Core, không phải là các ứng dụng một trang, hiện đang làm. Khi bạn sử dụng chúng để tạo một ứng dụng mới, wwwrootthư mục chỉ chứa một thư mục libchứa các phần phụ thuộc:

Thư mục wwwroot chứa thư mục lib với các phụ thuộc tĩnh

Nếu bạn xem xét kỹ các tệp hiện tại, bạn có thể thấy rằng ban đầu chúng được đặt ở đó cùng với Bower để tạo mẫu, nhưng điều đó có thể sẽ sớm thay đổi. Ý tưởng cơ bản là các tệp được sao chép một lần vào wwwrootthư mục để bạn có thể phụ thuộc vào chúng.

Để làm điều này, chúng ta có thể chỉ cần làm theo phần giới thiệu của Bootstrap và tải trực tiếp các tệp đã biên dịch . Như đã đề cập trên trang web tải xuống, điều này không bao gồm jQuery , vì vậy chúng tôi cũng cần tải xuống riêng; nó có chứa Popper.js mặc dù nếu chúng tôi chọn sử dụng bootstrap.bundletệp sau này — chúng tôi sẽ thực hiện. Đối với jQuery, chúng ta có thể chỉ cần lấy một tệp “nén, sản xuất” từ trang web tải xuống (nhấp chuột phải vào liên kết và chọn "Lưu liên kết dưới dạng ..." từ menu).

Điều này để lại cho chúng tôi một số tệp sẽ chỉ đơn giản là giải nén và sao chép vào wwwrootthư mục. Chúng tôi cũng có thể tạo một libthư mục để làm rõ ràng rằng đây là những phần phụ thuộc bên ngoài:

Thư mục wwwroot chứa thư mục lib với các phụ thuộc đã cài đặt của chúng tôi

Đó là tất cả những gì chúng ta cần, vì vậy bây giờ chúng ta chỉ cần điều chỉnh _Layout.cshtmltệp của mình để bao gồm các phụ thuộc đó. Để làm được điều đó, chúng tôi thêm khối sau vào <head>:

<environment include="Development">
    <link rel="stylesheet" href="~/lib/css/bootstrap.css" />
</environment>
<environment exclude="Development">
    <link rel="stylesheet" href="~/lib/css/bootstrap.min.css" />
</environment>

Và khối sau ở cuối <body>:

<environment include="Development">
    <script src="~/lib/js/jquery-3.3.1.js"></script>
    <script src="~/lib/js/bootstrap.bundle.js"></script>
</environment>
<environment exclude="Development">
    <script src="~/lib/js/jquery-3.3.1.min.js"></script>
    <script src="~/lib/js/bootstrap.bundle.min.js"></script>
</environment>

Bạn cũng có thể chỉ bao gồm các phiên bản rút gọn và bỏ qua trình <environment>trợ giúp thẻ ở đây để làm cho nó đơn giản hơn một chút. Nhưng đó là tất cả những gì bạn cần làm để bắt đầu.

Sự phụ thuộc từ NPM

Cách hiện đại hơn, cũng nếu bạn muốn cập nhật các phần phụ thuộc của mình, là lấy các phần phụ thuộc từ kho gói NPM. Bạn có thể sử dụng NPM hoặc Yarn cho việc này; trong ví dụ của tôi, tôi sẽ sử dụng NPM.

Để bắt đầu, chúng ta cần tạo một package.jsontệp cho dự án của mình, để chúng ta có thể chỉ định các phụ thuộc của mình. Để làm điều này, chúng tôi chỉ cần thực hiện điều đó từ hộp thoại “Thêm mục mới”:

Thêm mục mới: tệp cấu hình npm

Khi chúng ta có điều đó, chúng ta cần chỉnh sửa nó để bao gồm các phụ thuộc của chúng ta. Nó sẽ giống như thế này:

{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "devDependencies": {
    "bootstrap": "4.0.0",
    "jquery": "3.3.1",
    "popper.js": "1.12.9"
  }
}

Bằng cách lưu, Visual Studio sẽ chạy NPM để cài đặt các phụ thuộc cho chúng tôi. Chúng sẽ được cài đặt vào node_modulesthư mục. Vì vậy, những gì còn lại cần làm là lấy các tệp từ đó vào wwwrootthư mục của chúng tôi . Có một số tùy chọn để làm điều đó:

bundleconfig.json để đóng gói và rút gọn

Chúng tôi có thể sử dụng một trong những cách khác nhau để sử dụng một bundleconfig.jsongói và rút gọn, như được giải thích trong tài liệu . Một cách rất dễ dàng là chỉ cần sử dụng gói BuildBundlerMinifier NuGet để tự động thiết lập nhiệm vụ xây dựng cho việc này.

Sau khi cài đặt gói đó, chúng ta cần tạo một bundleconfig.jsonở gốc của dự án với nội dung sau:

[
  {
    "outputFileName": "wwwroot/vendor.min.css",
    "inputFiles": [
      "node_modules/bootstrap/dist/css/bootstrap.min.css"
    ],
    "minify": { "enabled": false }
  },
  {
    "outputFileName": "wwwroot/vendor.min.js",
    "inputFiles": [
      "node_modules/jquery/dist/jquery.min.js",
      "node_modules/popper.js/dist/umd/popper.min.js",
      "node_modules/bootstrap/dist/js/bootstrap.min.js"
    ],
    "minify": { "enabled": false }
  }
]

Điều này về cơ bản định cấu hình tệp nào sẽ kết hợp thành tệp nào. Và khi chúng tôi xây dựng, chúng tôi có thể thấy rằng vendor.min.cssvendor.js.cssđược tạo chính xác. Vì vậy, tất cả những gì chúng ta cần làm là điều chỉnh _Layouts.htmllại để bao gồm các tệp đó:

<!-- inside <head> -->
<link rel="stylesheet" href="~/vendor.min.css" />

<!-- at the end of <body> -->
<script src="~/vendor.min.js"></script>

Sử dụng trình quản lý tác vụ như Gulp

Nếu chúng ta muốn chuyển sang phát triển phía máy khách nhiều hơn một chút, chúng ta cũng có thể bắt đầu sử dụng các công cụ mà chúng ta sẽ sử dụng ở đó. Ví dụ như Webpack , một công cụ xây dựng được sử dụng rất phổ biến cho mọi thứ. Nhưng chúng ta cũng có thể bắt đầu với một trình quản lý tác vụ đơn giản hơn như Gulp và tự mình thực hiện một số bước cần thiết.

Đối với điều đó, chúng tôi thêm một gulpfile.jsvào thư mục gốc của chúng tôi, với các nội dung sau:

const gulp = require('gulp');
const concat = require('gulp-concat');

const vendorStyles = [
    "node_modules/bootstrap/dist/css/bootstrap.min.css"
];
const vendorScripts = [
    "node_modules/jquery/dist/jquery.min.js",
    "node_modules/popper.js/dist/umd/popper.min.js",
    "node_modules/bootstrap/dist/js/bootstrap.min.js",
];

gulp.task('build-vendor-css', () => {
    return gulp.src(vendorStyles)
        .pipe(concat('vendor.min.css'))
        .pipe(gulp.dest('wwwroot'));
});

gulp.task('build-vendor-js', () => {
    return gulp.src(vendorScripts)
        .pipe(concat('vendor.min.js'))
        .pipe(gulp.dest('wwwroot'));
});

gulp.task('build-vendor', gulp.parallel('build-vendor-css', 'build-vendor-js'));

gulp.task('default', gulp.series('build-vendor'));

Bây giờ, chúng ta cũng cần điều chỉnh package.jsonđể có các phụ thuộc vào gulpgulp-concat:

{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "devDependencies": {
    "bootstrap": "4.0.0",
    "gulp": "^4.0.2",
    "gulp-concat": "^2.6.1",
    "jquery": "3.3.1",
    "popper.js": "1.12.9"
  }
}

Cuối cùng, chúng tôi chỉnh sửa của chúng tôi .csprojđể thêm tác vụ sau để đảm bảo rằng tác vụ Gulp của chúng tôi chạy khi chúng tôi xây dựng dự án:

<Target Name="RunGulp" BeforeTargets="Build">
  <Exec Command="node_modules\.bin\gulp.cmd" />
</Target>

Bây giờ, khi chúng tôi xây dựng, defaulttác vụ Gulp sẽ chạy, tác vụ này chạy các build-vendortác vụ, sau đó xây dựng tác vụ của chúng tôi vendor.min.cssvendor.min.jsgiống như chúng tôi đã làm trước đây. Vì vậy, sau khi điều chỉnh _Layout.cshtmlgiống như trên, chúng ta có thể sử dụng jQuery và Bootstrap.

Mặc dù thiết lập ban đầu của Gulp phức tạp hơn một chút so với thiết lập bundleconfig.jsonở trên, nhưng bây giờ chúng ta đã bước vào thế giới Node và có thể bắt đầu sử dụng tất cả các công cụ thú vị khác ở đó. Vì vậy, nó có thể đáng để bắt đầu với điều này.

Phần kết luận

Mặc dù điều này đột nhiên trở nên phức tạp hơn rất nhiều so với chỉ sử dụng Bower, nhưng chúng tôi cũng có được rất nhiều quyền kiểm soát với những tùy chọn mới đó. Ví dụ, bây giờ chúng ta có thể quyết định những tệp nào thực sự được bao gồm trong wwwrootthư mục và chúng trông chính xác như thế nào. Và chúng tôi cũng có thể sử dụng điều này để thực hiện những bước đầu tiên vào thế giới phát triển phía máy khách với Node, điều này ít nhất sẽ giúp ích một chút cho đường cong học tập.


1
Khi sử dụng phương pháp npm, tôi gặp phải lỗi như "Uncaught SyntaxError: Xuất mã thông báo không mong muốn". Để khắc phục điều này, tôi đã chuyển sang tệp popper.js umd "node_modules / popper.js / dist / umd / popper.min.js". Nếu không, một trong những câu trả lời hay nhất mà tôi từng thấy trên ngăn xếp, cảm ơn bạn.
James Blake

2
@user Nghe có vẻ như bạn đang sử dụng phiên bản Node rất cũ. Bạn có thể xem phiên bản bằng cách chạy node -vvà tải phiên bản hiện tại tại đây trên nodejs.org
poke

62
CƯỜI LỚN. Tôi phải cười nếu không tôi sẽ khóc. 17 năm phát triển .Net bằng cách sử dụng công cụ hỗ trợ của Visual Studio, và nó đã đi đến đâu? Cá nhân tôi không thấy điều này tiến triển như thế nào. Nếu phải mất nhiều công sức như vậy chỉ để thêm kiểu Bootstrap vào một dự án web thì đã xảy ra lỗi nghiêm trọng.
camainc

11
@camainc Nếu có gì thì hãy đổ lỗi cho sự phát triển của hệ sinh thái JavaScript. Điều này thực sự không liên quan đến .NET hoặc Visual Studio cả. Giải pháp đơn giản vẫn là chỉ cần tải xuống các tệp theo cách thủ công và sau đó thêm chúng vào thư mục gốc của bạn. Đó chỉ là cách nó hoạt động suốt những năm trước đó. - Và đối với những gì đáng giá, Microsoft đang làm việc trên công cụ VS mới để làm cho quá trình này đơn giản hơn (và có thể cập nhật).
poke

3
@ ozzy432836, tôi biết đó không phải là vấn đề bootstrap và tôi chưa bao giờ nói là như vậy. Đó là một vấn đề phát triển chung với tất cả mọi người dường như đang theo đuổi khuôn khổ mới tiếp theo. Tôi đã thấy rất nhiều thay đổi trong sự nghiệp của mình, nhưng không có gì giống như những gì đã xảy ra trong vài năm qua xung quanh Javascript. Thực sự đã rất kinh ngạc khi xem cộng đồng phát triển đang khuấy động hết khuôn khổ mới này đến khuôn khổ khác. Đối với việc liệu JS có phải là con đường phía trước hay không, ban giám khảo vẫn chưa quan tâm đến vấn đề đó, đặc biệt là với WASM và các dự án như Blazor trên đường chân trời.
camainc 31-07-18

56

Nhìn vào điều này, có vẻ như cách tiếp cận LibMan hoạt động tốt nhất cho nhu cầu của tôi với việc thêm Bootstrap. Tôi thích nó vì nó hiện đã được tích hợp sẵn trong Visual Studio 2017 (15.8 trở lên) và có các hộp thoại riêng.

Cập nhật 6/11/2020: bootstrap 4.1.3 hiện được thêm vào theo mặc định với VS-2019.5 (Cảm ơn Harald S. Hanssen đã chú ý).

Phương thức mặc định VS thêm vào các dự án sử dụng Bower nhưng có vẻ như nó đang trên đường thoát ra. Trong tiêu đề của trang bower Microsofts họ viết: Bower chỉ được duy trì. Khuyến nghị sử dụng LibManager

Sau một vài liên kết dẫn đến Sử dụng LibMan với ASP.NET Core trong Visual Studio , nơi nó hiển thị cách có thể thêm lib bằng Hộp thoại tích hợp:

Trong Solution Explorer, bấm chuột phải vào thư mục dự án mà các tệp sẽ được thêm vào. Chọn Thêm> Thư viện phía máy khách. Hộp thoại Thêm thư viện phía máy khách xuất hiện: [nguồn: Scott Addie 2018 ]

nhập mô tả hình ảnh ở đây

Sau đó, đối với bootstrap chỉ cần (1) chọn unkg, (2) gõ vào "bootstrap @ .." (3) Cài đặt. Sau đó, bạn chỉ muốn xác minh rằng tất cả nội dung trong _Layout.cshtml hoặc những nơi khác là chính xác. Chúng phải là một cái gì đó giống như href = "~ / lib / bootstrap / dist / js / bootstrap ..." )


1
Tôi có VS 4.7.02558 (Phiên bản Cộng đồng) và đây là tùy chọn dễ dàng nhất đối với tôi. Tôi đã sử dụng nó trong các dự án thực tế được tạo để nghiên cứu cho kỳ thi MS 70-486 (MVC), vì vậy tôi không thể trả lời về mức độ hiệu quả của điều này đối với các dự án đang chuẩn bị sản xuất.
Ed Gibbs

2
Đối với tôi, đây cũng là cách dễ dàng nhất để cài đặt công cụ với CÔNG CỤ TIÊU CHUẨN MS. Với các gợi ý trong bài đăng của bạn - thay đổi Nhà cung cấp thành unkg, nhập vào bootstrap @ 4., Tôi đã có thể cài đặt. Libman thực sự không phải là trực quan (trong trường hợp của tôi, tôi cũng đã phải nhập (điểm) sau 4, trước khi gói được cho thấy (tôi nghĩ, libman không hoạt động trong môi trường của tôi)..
FredyWenger

2
Chỉ xin nhắc lại: nếu bạn đang tìm Bootstrap trên CdnJS, hãy lưu ý rằng tên của nó là twitter-bootstrap như ban đầu nó được gọi.
D.Rosado

1
Trong Visual Studio 2019 (mới nhất trước ngày 11 tháng 6 năm 2020) - Tệp libman được tạo, nhưng tôi không thấy cửa sổ bật lên libman.
Harald S. Hanssen

1
Tôi đã thử nghiệm LibMan trên một số dự án và đó thực sự là cách để đi. Thật tệ là GUI không hoạt động, nhưng sau một vài lần thử, nó rất dễ sử dụng.
Harald S. Hanssen

18

Hãy thử Libman , nó đơn giản như Bower và bạn có thể chỉ định wwwroot / lib / làm thư mục tải xuống.


1
Chưa có trong bản phát hành VS2017: CẬP NHẬT: 24 tháng 5 năm 2018 - Có vẻ như LibMan đã không có mặt trong bản phát hành cuối cùng là 15.7. Đó là trong bản xem trước cho 15.8.x
kristianp

1
Có vẻ như tính năng này hiện đã ra mắt với bản phát hành 15.8 cuối cùng.
Kirk Larkin

Nó có sẵn bây giờ trong VS2017 V 15,8 và cách tiếp cận đơn giản hơn nhiều so với câu trả lời chấp nhận
Jemsworld

10

Bí quyết cho tôi là gì:

1) Nhấp chuột phải vào wwwroot> Thêm> Thư viện phía máy khách

2) Đã nhập "bootstrap" vào hộp tìm kiếm

3) Chọn "Chọn tệp cụ thể"

4) Cuộn xuống và chọn một thư mục. Trong trường hợp của tôi, tôi đã chọn "twitter-bootstrap"

5) Kiểm tra "css" và "js"

6) Nhấp vào "Cài đặt".

Một vài giây sau, tôi có tất cả thư mục wwwroot. Làm tương tự cho tất cả các gói phía máy khách mà bạn muốn thêm.


6

Libman dường như là công cụ được Microsoft ưa thích hiện nay. Nó được tích hợp trong Visual Studio 2017 (15.8).

bài viết này mô tả cách sử dụng nó và thậm chí cả cách thiết lập khôi phục được thực hiện bởi quá trình xây dựng.

Tài liệu của Bootstrap cho bạn biết những tệp nào bạn cần trong dự án của mình.

Ví dụ sau sẽ hoạt động như một cấu hình cho libman.json.

{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": [
  {
    "library": "twitter-bootstrap@4.2.1",
    "destination": "wwwroot/lib/bootstrap",
    "files": [
    "js/bootstrap.bundle.js",
    "css/bootstrap.min.css"
    ]
  },
  {
    "library": "jquery@3.3.1",
    "destination": "wwwroot/lib/jquery",
    "files": [
      "jquery.min.js"
    ]
  }
]

}


Cảm ơn, tôi đã theo dõi một cuốn sách Pro ASP.NET Core MVC 2 nói với tôi rằng hãy sử dụng Bower hiện đã lỗi thời. Tôi đã tìm kiếm xung quanh một lúc trước khi nhận ra rằng bạn có thể chỉ cần nhấp chuột phải vào dự án của mình và chọn Thêm -> Thư viện phía máy khách. Và điều đó sử dụng libman. Đó là tất cả được xây dựng trong.
TxRegex

4

Chúng tôi sử dụng bootstrap 4 trong lõi asp.net nhưng tham khảo các thư viện từ "npm" bằng cách sử dụng tiện ích mở rộng "Trình cài đặt gói" và thấy điều này tốt hơn Nuget cho các thư viện Javascript / CSS.

Sau đó, chúng tôi sử dụng tiện ích mở rộng "Bundler & Minifier" để sao chép các tệp có liên quan để phân phối (từ thư mục npm node_modules, nằm bên ngoài dự án) vào wwwroot như chúng tôi muốn để phát triển / triển khai.


4

Thật không may, bạn sẽ gặp khó khăn khi sử dụng NuGet để cài đặt Bootstrap (hoặc hầu hết các khung JavaScript / CSS khác) trên một dự án .NET Core. Nếu bạn nhìn vào cài đặt NuGet, nó cho bạn biết nó không tương thích:

nhập mô tả hình ảnh ở đây

nếu bạn phải biết các gói phụ thuộc cục bộ ở đâu, chúng hiện đang ở trong thư mục hồ sơ cục bộ của bạn. I E%userprofile%\.nuget\packages\bootstrap\4.0.0\content\Scripts .

Tuy nhiên, tôi đề nghị chuyển sang npm, hoặc bower - như trong câu trả lời của Saineshwar.


2

BS4 hiện đã có trên .NET Core 2.2 . Chắc chắn là trên trình cài đặt SDK 2.2.105 x64. Tôi đang chạy Visual Studio 2017 với nó. Cho đến nay rất tốt cho các dự án ứng dụng web mới.


2

Tại sao không chỉ sử dụng CDN? Trừ khi bạn cần chỉnh sửa mã BS, khi đó bạn chỉ cần tham chiếu các mã trong CDN.

Xem BS 4 CDN Tại đây:

https://www.w3schools.com/bootstrap4/bootstrap_get_started.asp

Ở cuối trang.


1
Việc sử dụng CDN thêm phụ thuộc vào thời gian chạy. Vì vậy, nếu CDN bị hỏng, trang web của bạn cũng vậy. Đó là một vấn đề bảo mật vì bất kỳ ai kiểm soát cdn có thể thay đổi các tệp phổ biến và đưa tập lệnh vào trang web của bạn. Đây cũng là một vấn đề về quyền riêng tư vì trình duyệt của người dùng yêu cầu tệp từ máy chủ của bên thứ ba chứ không phải của chính bạn.
TxRegex

3
@TxRegex ở một số giai đoạn, người ta thực sự khuyến nghị rằng các tham chiếu đến CDN thay vì máy chủ của ứng dụng web; bởi vì trình duyệt của người dùng có thể đã lưu vào bộ đệm một thư viện phổ biến như Bootstrap trong khi duyệt các trang web khác. Nhưng bất cứ điều gì ...
joedotnot

0

Sử dụng tệp cấu hình nmp (thêm nó vào dự án web của bạn) sau đó thêm các gói cần thiết theo cách giống như cách chúng tôi đã sử dụng bower.json và lưu. Visual studio sẽ tải xuống và cài đặt nó. Bạn sẽ tìm thấy gói dưới nút nmp của dự án của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.