Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
2d26cbb2
Unverified
Commit
2d26cbb2
authored
May 08, 2020
by
Jonah Williams
Committed by
GitHub
May 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] reduce initial cache size on web (#56103)
parent
960b7571
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
126 additions
and
21 deletions
+126
-21
web.dart
packages/flutter_tools/lib/src/build_system/targets/web.dart
+102
-20
web_test.dart
...ols/test/general.shard/build_system/targets/web_test.dart
+24
-1
No files found.
packages/flutter_tools/lib/src/build_system/targets/web.dart
View file @
2d26cbb2
...
...
@@ -357,7 +357,8 @@ class WebServiceWorker extends Target {
final
Map
<
String
,
String
>
urlToHash
=
<
String
,
String
>{};
for
(
final
File
file
in
contents
)
{
// Do not force caching of source maps.
if
(
file
.
path
.
endsWith
(
'main.dart.js.map'
))
{
if
(
file
.
path
.
endsWith
(
'main.dart.js.map'
)
||
file
.
path
.
endsWith
(
'.part.js.map'
))
{
continue
;
}
final
String
url
=
globals
.
fs
.
path
.
toUri
(
...
...
@@ -376,7 +377,15 @@ class WebServiceWorker extends Target {
final
File
serviceWorkerFile
=
environment
.
outputDir
.
childFile
(
'flutter_service_worker.js'
);
final
Depfile
depfile
=
Depfile
(
contents
,
<
File
>[
serviceWorkerFile
]);
final
String
serviceWorker
=
generateServiceWorker
(
urlToHash
);
final
String
serviceWorker
=
generateServiceWorker
(
urlToHash
,
<
String
>[
'main.dart.js'
,
'/'
,
'index.html'
,
'assets/LICENSE'
,
'assets/AssetManifest.json'
,
if
(
urlToHash
.
containsKey
(
'assets/FontManifest.json'
))
'assets/FontManifest.json'
,
]);
serviceWorkerFile
.
writeAsStringSync
(
serviceWorker
);
final
DepfileService
depfileService
=
DepfileService
(
...
...
@@ -393,40 +402,113 @@ class WebServiceWorker extends Target {
/// Generate a service worker with an app-specific cache name a map of
/// resource files.
///
///
We embed
file hashes directly into the worker so that the byte for byte
///
The tool embeds
file hashes directly into the worker so that the byte for byte
/// invalidation will automatically reactivate workers whenever a new
/// version is deployed.
// TODO(jonahwilliams): on re-activate, only evict stale assets.
String
generateServiceWorker
(
Map
<
String
,
String
>
resources
)
{
String
generateServiceWorker
(
Map
<
String
,
String
>
resources
,
List
<
String
>
coreBundle
)
{
return
'''
'
use
strict
';
const MANIFEST = '
flutter
-
app
-
manifest
';
const TEMP = '
flutter
-
temp
-
cache
';
const CACHE_NAME = '
flutter
-
app
-
cache
';
const RESOURCES = {
${resources.entries.map((MapEntry<String, String> entry) => '"${entry.key}
": "
${entry.value}
"'
).
join
(
",
\n
"
)}
};
self
.
addEventListener
(
'activate'
,
function
(
event
)
{
event
.
waitUntil
(
caches
.
keys
().
then
(
function
(
cacheName
)
{
return
caches
.
delete
(
cacheName
);
}).
then
(
function
(
_
)
{
return
caches
.
open
(
CACHE_NAME
);
}).
then
(
function
(
cache
)
{
return
cache
.
addAll
(
Object
.
keys
(
RESOURCES
));
// The application shell files that are downloaded before a service worker can
// start.
const
CORE
=
[
$
{
coreBundle
.
map
((
String
file
)
=>
'"
$file
"'
).
join
(
',
\n
'
)}];
// During install, the TEMP cache is populated with the application shell files.
self
.
addEventListener
(
"install"
,
(
event
)
=>
{
return
event
.
waitUntil
(
caches
.
open
(
TEMP
).
then
((
cache
)
=>
{
return
cache
.
addAll
(
CORE
);
})
);
});
self
.
addEventListener
(
'fetch'
,
function
(
event
)
{
event
.
respondWith
(
caches
.
match
(
event
.
request
)
.
then
(
function
(
response
)
{
if
(
response
)
{
return
response
;
// During activate, the cache is populated with the temp files downloaded in
// install. If this service worker is upgrading from one with a saved
// MANIFEST, then use this to retain unchanged resource files.
self
.
addEventListener
(
"activate"
,
function
(
event
)
{
return
event
.
waitUntil
(
async
function
()
{
try
{
var
contentCache
=
await
caches
.
open
(
CACHE_NAME
);
var
tempCache
=
await
caches
.
open
(
TEMP
);
var
manifestCache
=
await
caches
.
open
(
MANIFEST
);
var
manifest
=
await
manifestCache
.
match
(
'manifest'
);
// When there is no prior manifest, clear the entire cache.
if
(!
manifest
)
{
await
caches
.
delete
(
CACHE_NAME
);
for
(
var
request
of
await
tempCache
.
keys
())
{
var
response
=
await
tempCache
.
match
(
request
);
await
contentCache
.
put
(
request
,
response
);
}
return
fetch
(
event
.
request
);
await
caches
.
delete
(
TEMP
);
// Save the manifest to make future upgrades efficient.
await
manifestCache
.
put
(
'manifest'
,
new
Response
(
JSON
.
stringify
(
RESOURCES
)));
return
;
}
var
oldManifest
=
await
manifest
.
json
();
var
origin
=
self
.
location
.
origin
;
for
(
var
request
of
await
contentCache
.
keys
())
{
var
key
=
request
.
url
.
substring
(
origin
.
length
+
1
);
if
(
key
==
""
)
{
key
=
"/"
;
}
// If a resource from the old manifest is not in the new cache, or if
// the MD5 sum has changed, delete it. Otherwise the resource is left
// in the cache and can be reused by the new service worker.
if
(!
RESOURCES
[
key
]
||
RESOURCES
[
key
]
!=
oldManifest
[
key
])
{
await
contentCache
.
delete
(
request
);
}
}
// Populate the cache with the app shell TEMP files, potentially overwriting
// cache files preserved above.
for
(
var
request
of
await
tempCache
.
keys
())
{
var
response
=
await
tempCache
.
match
(
request
);
await
contentCache
.
put
(
request
,
response
);
}
await
caches
.
delete
(
TEMP
);
// Save the manifest to make future upgrades efficient.
await
manifestCache
.
put
(
'manifest'
,
new
Response
(
JSON
.
stringify
(
RESOURCES
)));
return
;
}
catch
(
err
)
{
// On an unhandled exception the state of the cache cannot be guaranteed.
console
.
error
(
'Failed to upgrade service worker: '
+
err
);
await
caches
.
delete
(
CACHE_NAME
);
await
caches
.
delete
(
TEMP
);
await
caches
.
delete
(
MANIFEST
);
}
}());
});
// The fetch handler redirects requests for RESOURCE files to the service
// worker cache.
self
.
addEventListener
(
"fetch"
,
(
event
)
=>
{
var
origin
=
self
.
location
.
origin
;
var
key
=
event
.
request
.
url
.
substring
(
origin
.
length
+
1
);
// If the URL is not the the RESOURCE list, skip the cache.
if
(!
RESOURCES
[
key
])
{
return
event
.
respondWith
(
fetch
(
event
.
request
));
}
event
.
respondWith
(
caches
.
open
(
CACHE_NAME
)
.
then
((
cache
)
=>
{
return
cache
.
match
(
event
.
request
).
then
((
response
)
=>
{
// Either respond with the cached resource, or perform a fetch and
// lazily populate the cache.
return
response
||
fetch
(
event
.
request
).
then
((
response
)
=>
{
cache
.
put
(
event
.
request
,
response
.
clone
());
return
response
;
});
})
})
);
});
''';
}
packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
View file @
2d26cbb2
...
...
@@ -463,11 +463,17 @@ void main() {
}));
test
(
'Generated service worker correctly inlines file hashes'
,
()
{
final
String
result
=
generateServiceWorker
(<
String
,
String
>{
'/foo'
:
'abcd'
});
final
String
result
=
generateServiceWorker
(<
String
,
String
>{
'/foo'
:
'abcd'
}
,
<
String
>[]
);
expect
(
result
,
contains
(
'{
\n
"/foo": "abcd"
\n
};'
));
});
test
(
'Generated service worker includes core files'
,
()
{
final
String
result
=
generateServiceWorker
(<
String
,
String
>{
'/foo'
:
'abcd'
},
<
String
>[
'foo'
,
'bar'
]);
expect
(
result
,
contains
(
'"foo",
\n
"bar"'
));
});
test
(
'WebServiceWorker generates a service_worker for a web resource folder'
,
()
=>
testbed
.
run
(()
async
{
environment
.
outputDir
.
childDirectory
(
'a'
).
childFile
(
'a.txt'
)
..
createSync
(
recursive:
true
)
...
...
@@ -497,6 +503,23 @@ void main() {
contains
(
'"index.html": "d41d8cd98f00b204e9800998ecf8427e"'
));
expect
(
environment
.
buildDir
.
childFile
(
'service_worker.d'
),
exists
);
}));
test
(
'WebServiceWorker does not cache source maps'
,
()
=>
testbed
.
run
(()
async
{
environment
.
outputDir
.
childFile
(
'main.dart.js'
)
.
createSync
(
recursive:
true
);
environment
.
outputDir
.
childFile
(
'main.dart.js.map'
)
.
createSync
(
recursive:
true
);
await
const
WebServiceWorker
().
build
(
environment
);
// No caching of source maps.
expect
(
environment
.
outputDir
.
childFile
(
'flutter_service_worker.js'
).
readAsStringSync
(),
isNot
(
contains
(
'"main.dart.js.map"'
)));
// Expected twice, once for RESOURCES and once for CORE.
expect
(
environment
.
outputDir
.
childFile
(
'flutter_service_worker.js'
).
readAsStringSync
(),
contains
(
'"main.dart.js"'
));
}));
}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment