如何解决Tailwind CSS文件很大2.42 MIB我如何使用Laravel减小此文件的大小?
Tailwind CSS文件很大2.42 mib,我如何使用laravel减小此文件的大小?
解决方法
最好的策略是使用生成特定于您的特定CSS并将其部署在您自己的CDN上
下面的示例说明了如何为简单的HTML项目配置TailwindCSS
- 第一步:创建一个package.json文件
import 'package:flutter/material.dart';
class SearchItem<TValue> {
/// Item value
final TValue value;
/// Item display text
final String text;
SearchItem(this.value,this.text);
}
class SearchPage extends StatefulWidget {
final List<SearchItem> data;
final Icon icon;
final TextStyle textStyle;
final Color color;
final EdgeInsetsGeometry padding;
final String title;
SearchPage(
{this.data,this.icon,this.textStyle,this.padding,this.color,this.title});
@override
State<StatefulWidget> createState() {
return new _SearchPageState();
}
}
class _SearchPageState extends State<SearchPage> {
TextEditingController controller = new TextEditingController();
List<SearchItem> _searchList = [];
List<SearchItem> _dataList = [];
@override
void initState() {
super.initState();
_dataList = widget.data;
}
@override
void dispose() {
_searchList.clear();
controller.dispose();
super.dispose();
}
_onChange(SearchItem selection) {
Navigator.pop(context,selection);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
backgroundColor: widget.color,title: new Text(widget.title ?? 'Search Page'),elevation: 0.0,),body: new Column(
children: <Widget>[
new Container(
color: widget.color,child: new Padding(
padding: widget.padding,child: new Card(
child: new ListTile(
leading: new Icon(Icons.search),title: new TextField(
controller: controller,decoration: new InputDecoration(
hintText: 'Search',border: InputBorder.none),onChanged: onSearchTextChanged,trailing: new IconButton(
icon: new Icon(Icons.cancel),onPressed: () {
controller.clear();
onSearchTextChanged('');
},new Expanded(
child: _searchList.length != 0 || controller.text.isNotEmpty
? new ListView.builder(
itemCount: _searchList.length,itemBuilder: (context,i) {
return new Card(
color: widget.color,child: FlatButton(
onPressed: () {
Navigator.pop(context,_searchList[i]);
},child: new ListTile(
leading: widget.icon,title: new Text(_searchList[i].text,style: widget.textStyle),margin: const EdgeInsets.all(0.0),);
},)
: new ListView.builder(
itemCount: _dataList.length,index) {
return new Card(
color: widget.color,child: FlatButton(
onPressed: () {
_onChange(_dataList[index]);
},child: new ListTile(
leading: widget.icon,title: new Text(
_dataList[index].text,style: widget.textStyle,)),],);
}
onSearchTextChanged(String text) async {
_searchList.clear();
if (text.isEmpty) {
setState(() {});
return;
}
_dataList.forEach((userDetail) {
if (userDetail.text.startsWith(text.toLowerCase()) ||
userDetail.text.toLowerCase().startsWith(
text.toLowerCase())) if (_searchList.contains(userDetail) ==
false) {
_searchList.add(userDetail);
}
});
setState(() {});
}
}
class FlutterSearchPanel<TValue> extends StatefulWidget {
@required
final Function onChanged;
@required
final List<SearchItem<TValue>> data;
final String title;
final Icon icon;
final TextStyle textStyle;
final Color color;
final EdgeInsetsGeometry padding;
final TValue selected;
FlutterSearchPanel(
{this.onChanged,this.title,this.data,this.selected,this.color});
@override
State<StatefulWidget> createState() {
return new _FlutterSearchPanelState<TValue>();
}
}
class _FlutterSearchPanelState<TValue>
extends State<FlutterSearchPanel<TValue>> {
SearchItem<TValue> selection;
final _defaultIcon = Icons.label;
final TextStyle _defaultTextStyle =
new TextStyle(color: Colors.red,fontSize: 22.0);
final Color _defaultColor = Colors.red;
final EdgeInsetsGeometry _defaultPadding = EdgeInsets.all(10.0);
@override
void initState() {
super.initState();
if (widget.selected != null) {
selection = widget.data.firstWhere(
(item) => item.value == widget.selected,orElse: () => selection = widget.data[0]);
} else {
selection = widget.data[0];
}
}
@override
void dispose() {
super.dispose();
}
_openSearchPage() async {
final result = await Navigator.push(
context,MaterialPageRoute(
builder: (context) => SearchPage(
title: widget.title,data: widget.data,icon: widget.icon ?? _defaultIcon,padding: widget.padding ?? _defaultPadding,color: widget.color ?? _defaultColor,textStyle: widget.textStyle ?? _defaultTextStyle)),);
if (result != null) {
setState(() {
selection = result;
});
if (widget.onChanged != null) {
widget.onChanged((result as SearchItem<TValue>).value);
}
}
}
@override
Widget build(BuildContext context) => new InkWell(
onTap: _openSearchPage,child: SizedBox(
//height: MediaQuery.of(context).size.height,child: Container(
decoration: BoxDecoration(border: Border.all(color: Colors.black)),child: Text(
selection.text,textAlign: TextAlign.right,style: widget.textStyle ?? Theme.of(context).textTheme.button,);
}
class SuspendedListPicker extends StatefulWidget {
SuspendedListPicker({
Key key,this.onChanged,}) : super(key: key);
List<SearchItem<int>> data = [];
final Function onChanged;
@override
_SuspendedListPickerState createState() => _SuspendedListPickerState();
}
class _SuspendedListPickerState extends State<SuspendedListPicker> {
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width * 0.55,child: FlutterSearchPanel<int>(
title: "Selecione",//padding: EdgeInsets.all(10.0),icon: Icon(Icons.label,color: Colors.blue[300]),color: Colors.white,textStyle: TextStyle(color: Colors.black,fontSize: 28.0),onChanged: (value) {
widget.onChanged(value);
},));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',theme: ThemeData(
primarySwatch: Colors.blue,visualDensity: VisualDensity.adaptivePlatformDensity,home: MyHomePage(title: 'Flutter Demo Home Page'),);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key,this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int currentValue;
List<SearchItem<int>> data = [
SearchItem(0,'This'),SearchItem(1,'is'),SearchItem(2,'a'),SearchItem(3,'test'),SearchItem(4,'.'),];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
SuspendedListPicker(
data: data,onChanged: (value) {
setState(() {
currentValue = value;
});
},Text('current value $currentValue'),);
}
}
- 添加tailwindcss postcss-cli和autoprefixer
yarn init
纱线添加tailwindcss postcss-cli自动前缀-D
- 为TailwindCSS创建默认配置文件
yarn add tailwindcss postcss-cli autoprefixer -D
- 创建一个postcss.config.js文件
npx tailwind init tailwind.js -full
- 编辑postcss.config.js
touch postcss.config.js
- 创建如下的tailwind.css
const tailwindcss = require('tailwindcss');
module.exports = {
plugins: [
tailwindcss('./tailwind.js'),require('autoprefixer')
],purge: [
'./src/**/*.html',};
- 使用postcss生成样式表style.css
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
- 在项目中使用样式表
npx postcss tailwind.css -o style.css
- 在CDN上部署style.css
(可能的CDN:CloudFront / Netlify)
,编辑您的 tailwind.config.js 并设置 purge.enabled = true:
const tailwindcss = require('tailwindcss');
module.exports = {
purge: {
enabled: true,content: ['./src/**/*.{vue,js,ts,jsx,tsx}']
},...
};
Tailwind CSS - Optimizing for Production
,简单,请勿使用。从概念上讲,Tailwind在CDN中非常大且无法使用,而不会丢失其具有的最佳功能。
通过CDN使用Tailwind
您无法自定义Tailwind的默认主题
您不能使用任何指令,例如@ apply,@ variants等。
您无法启用分组悬停之类的功能
您无法安装第三方插件
您不能摇晃未使用的样式
@ https://tailwindcss.com/docs/installation#using-tailwind-via-cdn
如果使用它,请确保正确配置css / js文件的导航器缓存时间,否则您的网站用户会感到不舒服。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。