Frontend: Extract CSS imports into files (#94655)

* build(webpack): extract css imports into files including node_modules

* feat(webassets): add cssfiles to entrypoint assets for extracted css files

* feat(views): add entrypoint css link tags to html templates

* feat(webassets): set CDN prefix for CSS files

* test(webassets): trim down sample-assets-manifest, fix failing snapshot tests

* Update pkg/api/webassets/webassets_test.go

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>

* build(webpack): remove css module loader

---------

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
pull/94531/head
Jack Westbrook 1 year ago committed by GitHub
parent 65fc7cf004
commit cfb46c8003
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      pkg/api/dtos/index.go
  2. 1961
      pkg/api/webassets/testdata/sample-assets-manifest.json
  3. 22
      pkg/api/webassets/webassets.go
  4. 126
      pkg/api/webassets/webassets_test.go
  5. 6
      public/views/index.html
  6. 69
      public/views/swagger.html
  7. 3
      scripts/webpack/sass.rule.js
  8. 4
      scripts/webpack/webpack.common.js

@ -39,9 +39,11 @@ type IndexViewData struct {
type EntryPointAssets struct { type EntryPointAssets struct {
ContentDeliveryURL string `json:"cdn,omitempty"` ContentDeliveryURL string `json:"cdn,omitempty"`
JSFiles []EntryPointAsset `json:"jsFiles"` JSFiles []EntryPointAsset `json:"jsFiles"`
CSSFiles []EntryPointAsset `json:"cssFiles"`
Dark string `json:"dark"` Dark string `json:"dark"`
Light string `json:"light"` Light string `json:"light"`
Swagger []EntryPointAsset `json:"swagger"` Swagger []EntryPointAsset `json:"swagger"`
SwaggerCSSFiles []EntryPointAsset `json:"swaggerCssFiles"`
} }
type EntryPointAsset struct { type EntryPointAsset struct {
@ -59,7 +61,13 @@ func (a *EntryPointAssets) SetContentDeliveryURL(prefix string) {
for i, p := range a.JSFiles { for i, p := range a.JSFiles {
a.JSFiles[i].FilePath = prefix + p.FilePath a.JSFiles[i].FilePath = prefix + p.FilePath
} }
for i, p := range a.CSSFiles {
a.CSSFiles[i].FilePath = prefix + p.FilePath
}
for i, p := range a.Swagger { for i, p := range a.Swagger {
a.Swagger[i].FilePath = prefix + p.FilePath a.Swagger[i].FilePath = prefix + p.FilePath
} }
for i, p := range a.SwaggerCSSFiles {
a.SwaggerCSSFiles[i].FilePath = prefix + p.FilePath
}
} }

File diff suppressed because it is too large Load Diff

@ -134,10 +134,12 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
} }
rsp := &dtos.EntryPointAssets{ rsp := &dtos.EntryPointAssets{
JSFiles: make([]dtos.EntryPointAsset, 0, len(entryPoints.App.Assets.JS)), JSFiles: make([]dtos.EntryPointAsset, 0, len(entryPoints.App.Assets.JS)),
Dark: entryPoints.Dark.Assets.CSS[0], CSSFiles: make([]dtos.EntryPointAsset, 0, len(entryPoints.App.Assets.CSS)),
Light: entryPoints.Light.Assets.CSS[0], Dark: entryPoints.Dark.Assets.CSS[0],
Swagger: make([]dtos.EntryPointAsset, 0, len(entryPoints.Swagger.Assets.JS)), Light: entryPoints.Light.Assets.CSS[0],
Swagger: make([]dtos.EntryPointAsset, 0, len(entryPoints.Swagger.Assets.JS)),
SwaggerCSSFiles: make([]dtos.EntryPointAsset, 0, len(entryPoints.Swagger.Assets.CSS)),
} }
for _, entry := range entryPoints.App.Assets.JS { for _, entry := range entryPoints.App.Assets.JS {
@ -146,11 +148,23 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
Integrity: integrity[entry], Integrity: integrity[entry],
}) })
} }
for _, entry := range entryPoints.App.Assets.CSS {
rsp.CSSFiles = append(rsp.CSSFiles, dtos.EntryPointAsset{
FilePath: entry,
Integrity: integrity[entry],
})
}
for _, entry := range entryPoints.Swagger.Assets.JS { for _, entry := range entryPoints.Swagger.Assets.JS {
rsp.Swagger = append(rsp.Swagger, dtos.EntryPointAsset{ rsp.Swagger = append(rsp.Swagger, dtos.EntryPointAsset{
FilePath: entry, FilePath: entry,
Integrity: integrity[entry], Integrity: integrity[entry],
}) })
} }
for _, entry := range entryPoints.Swagger.Assets.CSS {
rsp.SwaggerCSSFiles = append(rsp.SwaggerCSSFiles, dtos.EntryPointAsset{
FilePath: entry,
Integrity: integrity[entry],
})
}
return rsp, nil return rsp, nil
} }

@ -18,29 +18,45 @@ func TestReadWebassets(t *testing.T) {
// fmt.Printf("%s\n", string(dto)) // fmt.Printf("%s\n", string(dto))
require.JSONEq(t, `{ require.JSONEq(t, `{
"jsFiles": [ "jsFiles": [
{ {
"filePath": "public/build/runtime~app.1140e4861852d9e6f2e2.js", "filePath": "public/build/runtime.js",
"integrity": "sha256-HwsNc3NYC6Ee9cwVjOiEvhAmcaoe8HIwlwiVu/gc+D4= sha384-tt6bizrzSNPJH+uQGvcBokWaWp34sh0jp015BO7ZAO7HujvBjlduOid/30hz64DK sha512-hC1VmDBaqkULR+iPfPyAY4ZwAa5BXrahre0UrvO7+gLIpv810eu3uCGm5YTm+lFb+YFuBPlJDC4X2DarrEc5sg==" "integrity": "sha256-tM4AGASn3Cb8139+wp3w6rlo3ELFAuUW7K4Pifx226o= sha384-DfxxsYWb0+RxiXOr+wtCSzAAYGecffq/iHyn6CN9tHmaORv1sS+rsrnlnJo2jPQD sha512-qSxdqrx0mJLY1mdkbKrkCyqOoIEgFqzCoY9+uIuFRIVDPFbb2nJy0NtaKMQvDJnAzIrJFwzwW1e250T4WqQNiQ=="
}, },
{ {
"filePath": "public/build/app.5e6b0a8f6800cdea4a51.js", "filePath": "public/build/default-packages_grafana-ui_src_components_Layout_Stack_Stack_tsx-packages_grafana-ui_src_com-2a3620.js",
"integrity": "sha256-xLLqXfNJ3+ybFt0Y3519SRZ8BkZvYm30epIE2y5EaIs= sha384-A/LoksVaN1WL6LO53SVm4KcBciyP6leDAdLLrxk13g0iPRMqOPEF+r7qEl0QnHp1 sha512-amLUBch//DibrSurQ2Zt5oUDvdhl48z3Scw7gqp2ASR0jcsLeev3RHcUJKrpW0GDTMRbUEAhIqFL9he2iYzg9g==" "integrity": "sha256-+0bPuBGKFGglkXvW4oPiolrNveozRLZVLUrbCYsbVcM= sha384-EIayAgykdDWmyilAuXo4ad96v3tRqdWZp+BHdeDpSSsbAMeg+eoBBbk2Yh219kDg sha512-+jn7kmQ9Id8aTIe66TD+vM+W19cTIVexEfkxbxgqXdJyJ72qalN6ccWyP1ro1w/E1R/laZGNLz1LBc1I4u2Isw=="
} },
], {
"dark": "public/build/grafana.dark.d27cc3e33cf31ab577e7.css", "filePath": "public/build/app.js",
"light": "public/build/grafana.light.e6be3c7d879fd499516e.css", "integrity": "sha256-IOZKp3piC3vddDXP5jy5rIw0vb0KKEOg/k9EGrIxskk= sha384-CBNr5W0pJ23LQMnz5BZI1iVBIExOmF/wpqkEnBtYu9R/yYJIzjpv8KT0a3TBulOi sha512-ockzlzgosuZvLittZrSzh8lexEIZF9iKpy6J9Ii4es3e4D34FpWhHJhDZGpxLVraX4ypLofrDp2Yy0sdUbdi7w=="
"swagger": [ }
{ ],
"filePath": "public/build/runtime~swagger.793c8e6ede4824f9b730.js", "cssFiles": [
"integrity": "sha256-cXK7bq3M16fgI1WgELNFabHXVvn84rPN960QwrmTKiQ= sha384-Ysrs6mXl6RUK5nyttGRFQh4ABbpqxnsckFdJFI7FTU9ZQnyXl04DCam0ADj6t43G sha512-l5lei1D6HlvLrxCVovMdwNhMLDc0zO7u/fJwIvASbi49HjuJRsn6cTw/ZBfeghtqBJF0mZeg+fXo0ZKriY8Wlg==" {
}, "filePath": "public/build/grafana.app.91aaa9d81398c147a57c.css",
{ "integrity": "sha256-77rfikk+dYkH82TOmcmleVoDOHZQdhzVX9gDLcgPbtQ= sha384-IOTlZ1IvTVq5ekKLoaE3/SoZ12K1eExOAnSw9BzkgQ3+RcyQpb1S5hO2w//IIkRB sha512-0Ct3uJBFQIkyxYTvMxseA1cphe2RivXQ2MCbiV0hEm5NzWPiY9sq2P4ay5dXz5v35c++4W47KaknoWlc83bQJQ=="
"filePath": "public/build/swagger.789d2ab30a8124d2a92c.js", }
"integrity": "sha256-zvXf9SHyzCHFvuOGphlImo8zbJ6jnJVXQOzUFNMPMW8= sha384-GLZ2Z9nV1opFHaQXC6pehHmy4XOBImvDk1w7b8QdYeyobarSrA93CzxjfrtCnA2Y sha512-CZ2oIrYuWGaGU+EZr4/KEFerOZU9XS2NELNNsIwtzs7Zcw/rroa4fU0PiZvXbeT+B2kUy1rGLAQ5nwgR0sQlNA==" ],
} "dark": "public/build/grafana.dark.722d809dba5a31f57d49.css",
] "light": "public/build/grafana.light.2fbd901d840329c18394.css",
}`, string(dto)) "swagger": [
{
"filePath": "public/build/runtime.js",
"integrity": "sha256-tM4AGASn3Cb8139+wp3w6rlo3ELFAuUW7K4Pifx226o= sha384-DfxxsYWb0+RxiXOr+wtCSzAAYGecffq/iHyn6CN9tHmaORv1sS+rsrnlnJo2jPQD sha512-qSxdqrx0mJLY1mdkbKrkCyqOoIEgFqzCoY9+uIuFRIVDPFbb2nJy0NtaKMQvDJnAzIrJFwzwW1e250T4WqQNiQ=="
},
{
"filePath": "public/build/swagger.js",
"integrity": "sha256-wLlip7zRYODW/TPcI5JZPRdmWirc1KD+UcNF+8V9RBk= sha384-6VGD+LgCpjMZN/ORSjWcrWa9diUzQO3OfEhP0D2ZluSwP4IT+0kH7KEeD9NVbojd sha512-vZOCFzBZBhd34yGv8z7P4Gw4WLVR9HjpuK0y6Kcw+pCBk5Dv9qHBg3ZVs6s0tOnUmiMWwgL4Ne8f+zgiuJVPqg=="
}
],
"swaggerCssFiles": [
{
"filePath": "public/build/grafana.swagger.2733d417270d5dd49373.css",
"integrity": "sha256-GNcHNgIAT7S+J4X7seFjlvNPC1bRhM15d0cQBm3VFoQ= sha384-ywztCBf8uF0tTFjC1mLth33RI2WuFURN3dRy7Bv2PheGzbWJpwlgo9+mtT2Zm7mO sha512-e4c+VedZGqcwLqwfdqRWonggRPO0gjJ7Z0YbXK5z4bFTsUIc+x8ycIJG+eQaf8cuHlsakG4hkWNkRwLBazcFAg=="
}
]
}`, string(dto))
assets.SetContentDeliveryURL("https://grafana-assets.grafana.net/grafana/10.3.0-64123/") assets.SetContentDeliveryURL("https://grafana-assets.grafana.net/grafana/10.3.0-64123/")
@ -49,30 +65,46 @@ func TestReadWebassets(t *testing.T) {
fmt.Printf("%s\n", string(dto)) fmt.Printf("%s\n", string(dto))
require.JSONEq(t, `{ require.JSONEq(t, `{
"cdn": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/", "cdn": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/",
"jsFiles": [ "jsFiles": [
{ {
"filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/runtime~app.1140e4861852d9e6f2e2.js", "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/runtime.js",
"integrity": "sha256-HwsNc3NYC6Ee9cwVjOiEvhAmcaoe8HIwlwiVu/gc+D4= sha384-tt6bizrzSNPJH+uQGvcBokWaWp34sh0jp015BO7ZAO7HujvBjlduOid/30hz64DK sha512-hC1VmDBaqkULR+iPfPyAY4ZwAa5BXrahre0UrvO7+gLIpv810eu3uCGm5YTm+lFb+YFuBPlJDC4X2DarrEc5sg==" "integrity": "sha256-tM4AGASn3Cb8139+wp3w6rlo3ELFAuUW7K4Pifx226o= sha384-DfxxsYWb0+RxiXOr+wtCSzAAYGecffq/iHyn6CN9tHmaORv1sS+rsrnlnJo2jPQD sha512-qSxdqrx0mJLY1mdkbKrkCyqOoIEgFqzCoY9+uIuFRIVDPFbb2nJy0NtaKMQvDJnAzIrJFwzwW1e250T4WqQNiQ=="
}, },
{ {
"filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/app.5e6b0a8f6800cdea4a51.js", "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/default-packages_grafana-ui_src_components_Layout_Stack_Stack_tsx-packages_grafana-ui_src_com-2a3620.js",
"integrity": "sha256-xLLqXfNJ3+ybFt0Y3519SRZ8BkZvYm30epIE2y5EaIs= sha384-A/LoksVaN1WL6LO53SVm4KcBciyP6leDAdLLrxk13g0iPRMqOPEF+r7qEl0QnHp1 sha512-amLUBch//DibrSurQ2Zt5oUDvdhl48z3Scw7gqp2ASR0jcsLeev3RHcUJKrpW0GDTMRbUEAhIqFL9he2iYzg9g==" "integrity": "sha256-+0bPuBGKFGglkXvW4oPiolrNveozRLZVLUrbCYsbVcM= sha384-EIayAgykdDWmyilAuXo4ad96v3tRqdWZp+BHdeDpSSsbAMeg+eoBBbk2Yh219kDg sha512-+jn7kmQ9Id8aTIe66TD+vM+W19cTIVexEfkxbxgqXdJyJ72qalN6ccWyP1ro1w/E1R/laZGNLz1LBc1I4u2Isw=="
} },
], {
"dark": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.dark.d27cc3e33cf31ab577e7.css", "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/app.js",
"light": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.light.e6be3c7d879fd499516e.css", "integrity": "sha256-IOZKp3piC3vddDXP5jy5rIw0vb0KKEOg/k9EGrIxskk= sha384-CBNr5W0pJ23LQMnz5BZI1iVBIExOmF/wpqkEnBtYu9R/yYJIzjpv8KT0a3TBulOi sha512-ockzlzgosuZvLittZrSzh8lexEIZF9iKpy6J9Ii4es3e4D34FpWhHJhDZGpxLVraX4ypLofrDp2Yy0sdUbdi7w=="
"swagger": [ }
{ ],
"filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/runtime~swagger.793c8e6ede4824f9b730.js", "cssFiles": [
"integrity": "sha256-cXK7bq3M16fgI1WgELNFabHXVvn84rPN960QwrmTKiQ= sha384-Ysrs6mXl6RUK5nyttGRFQh4ABbpqxnsckFdJFI7FTU9ZQnyXl04DCam0ADj6t43G sha512-l5lei1D6HlvLrxCVovMdwNhMLDc0zO7u/fJwIvASbi49HjuJRsn6cTw/ZBfeghtqBJF0mZeg+fXo0ZKriY8Wlg==" {
}, "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.app.91aaa9d81398c147a57c.css",
{ "integrity": "sha256-77rfikk+dYkH82TOmcmleVoDOHZQdhzVX9gDLcgPbtQ= sha384-IOTlZ1IvTVq5ekKLoaE3/SoZ12K1eExOAnSw9BzkgQ3+RcyQpb1S5hO2w//IIkRB sha512-0Ct3uJBFQIkyxYTvMxseA1cphe2RivXQ2MCbiV0hEm5NzWPiY9sq2P4ay5dXz5v35c++4W47KaknoWlc83bQJQ=="
"filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/swagger.789d2ab30a8124d2a92c.js", }
"integrity": "sha256-zvXf9SHyzCHFvuOGphlImo8zbJ6jnJVXQOzUFNMPMW8= sha384-GLZ2Z9nV1opFHaQXC6pehHmy4XOBImvDk1w7b8QdYeyobarSrA93CzxjfrtCnA2Y sha512-CZ2oIrYuWGaGU+EZr4/KEFerOZU9XS2NELNNsIwtzs7Zcw/rroa4fU0PiZvXbeT+B2kUy1rGLAQ5nwgR0sQlNA==" ],
} "dark": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.dark.722d809dba5a31f57d49.css",
] "light": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.light.2fbd901d840329c18394.css",
}`, string(dto)) "swagger": [
{
"filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/runtime.js",
"integrity": "sha256-tM4AGASn3Cb8139+wp3w6rlo3ELFAuUW7K4Pifx226o= sha384-DfxxsYWb0+RxiXOr+wtCSzAAYGecffq/iHyn6CN9tHmaORv1sS+rsrnlnJo2jPQD sha512-qSxdqrx0mJLY1mdkbKrkCyqOoIEgFqzCoY9+uIuFRIVDPFbb2nJy0NtaKMQvDJnAzIrJFwzwW1e250T4WqQNiQ=="
},
{
"filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/swagger.js",
"integrity": "sha256-wLlip7zRYODW/TPcI5JZPRdmWirc1KD+UcNF+8V9RBk= sha384-6VGD+LgCpjMZN/ORSjWcrWa9diUzQO3OfEhP0D2ZluSwP4IT+0kH7KEeD9NVbojd sha512-vZOCFzBZBhd34yGv8z7P4Gw4WLVR9HjpuK0y6Kcw+pCBk5Dv9qHBg3ZVs6s0tOnUmiMWwgL4Ne8f+zgiuJVPqg=="
}
],
"swaggerCssFiles": [
{
"filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.swagger.2733d417270d5dd49373.css",
"integrity": "sha256-GNcHNgIAT7S+J4X7seFjlvNPC1bRhM15d0cQBm3VFoQ= sha384-ywztCBf8uF0tTFjC1mLth33RI2WuFURN3dRy7Bv2PheGzbWJpwlgo9+mtT2Zm7mO sha512-e4c+VedZGqcwLqwfdqRWonggRPO0gjJ7Z0YbXK5z4bFTsUIc+x8ycIJG+eQaf8cuHlsakG4hkWNkRwLBazcFAg=="
}
]
}`, string(dto))
} }
func TestReadWebassetsFromCDN(t *testing.T) { func TestReadWebassetsFromCDN(t *testing.T) {

@ -18,6 +18,10 @@
<link rel="apple-touch-icon" sizes="180x180" href="[[.AppleTouchIcon]]" /> <link rel="apple-touch-icon" sizes="180x180" href="[[.AppleTouchIcon]]" />
<link rel="mask-icon" href="[[.Assets.ContentDeliveryURL]]public/img/grafana_mask_icon.svg" color="#F05A28" /> <link rel="mask-icon" href="[[.Assets.ContentDeliveryURL]]public/img/grafana_mask_icon.svg" color="#F05A28" />
[[range $asset := .Assets.CSSFiles]]
<link rel="stylesheet" href="[[$asset.FilePath]]" />
[[end]]
<!-- If theme is "system", we inject the stylesheets with javascript further down the page --> <!-- If theme is "system", we inject the stylesheets with javascript further down the page -->
[[ if eq .ThemeType "light" ]] [[ if eq .ThemeType "light" ]]
<link rel="stylesheet" href="[[.Assets.Light]]" /> <link rel="stylesheet" href="[[.Assets.Light]]" />
@ -170,7 +174,7 @@
.preloader--done .preloader__text--fail a { .preloader--done .preloader__text--fail a {
color: white; color: white;
} }
.theme-light .preloader--done .preloader__text--fail a { .theme-light .preloader--done .preloader__text--fail a {
color: rgb(31, 98, 224); color: rgb(31, 98, 224);
} }

@ -1,44 +1,39 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head>
[[ if and .CSPEnabled .IsDevelopmentEnv ]]
<!-- Cypress overwrites CSP headers in HTTP requests, so this is required for e2e tests-->
<meta http-equiv="Content-Security-Policy" content="[[.CSPContent]]" />
[[ end ]]
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<meta name="theme-color" content="#000" />
<head> <title>Grafana API Reference</title>
[[ if and .CSPEnabled .IsDevelopmentEnv ]]
<!-- Cypress overwrites CSP headers in HTTP requests, so this is required for e2e tests-->
<meta http-equiv="Content-Security-Policy" content="[[.CSPContent]]"/>
[[ end ]]
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<meta name="theme-color" content="#000" />
<title>Grafana API Reference</title> [[range $asset := .Assets.SwaggerCSSFiles]]
<link rel="stylesheet" href="[[$asset.FilePath]]" />
[[end]]
<link rel="stylesheet" href="[[.Assets.Light]]" /> <link rel="stylesheet" href="[[.Assets.Light]]" />
<link rel="icon" type="image/png" href="[[.FavIcon]]" /> <link rel="icon" type="image/png" href="[[.FavIcon]]" />
<link rel="apple-touch-icon" sizes="180x180" href="[[.AppleTouchIcon]]" /> <link rel="apple-touch-icon" sizes="180x180" href="[[.AppleTouchIcon]]" />
<link rel="mask-icon" href="[[.Assets.ContentDeliveryURL]]public/img/grafana_mask_icon.svg" color="#F05A28" /> <link rel="mask-icon" href="[[.Assets.ContentDeliveryURL]]public/img/grafana_mask_icon.svg" color="#F05A28" />
</head> </head>
<body> <body>
<noscript> <noscript> You need to enable JavaScript to run this app. </noscript>
You need to enable JavaScript to run this app. <script nonce="[[$.Nonce]]">
</noscript> [[if .Assets.ContentDeliveryURL]]
<script nonce="[[$.Nonce]]"> window.public_cdn_path = '[[.Assets.ContentDeliveryURL]]public/build/';
[[if .Assets.ContentDeliveryURL]] [[end]]
window.public_cdn_path = '[[.Assets.ContentDeliveryURL]]public/build/'; </script>
<div id="root"></div>
[[range $asset := .Assets.Swagger]]
<script nonce="[[$.Nonce]]" src="[[$asset.FilePath]]" type="text/javascript"></script>
[[end]] [[end]]
</script> <script></script>
<div id="root"></div> </body>
[[range $asset := .Assets.Swagger]] </html>
<script
nonce="[[$.Nonce]]"
src="[[$asset.FilePath]]"
type="text/javascript"
></script>
[[end]]
<script>
</script>
</body>
</html>

@ -5,8 +5,7 @@ const path = require('path');
module.exports = function (options) { module.exports = function (options) {
return { return {
test: /\.scss$/, test: /\.(sa|sc|c)ss$/,
exclude: /node_modules/,
use: [ use: [
MiniCssExtractPlugin.loader, MiniCssExtractPlugin.loader,
{ {

@ -96,10 +96,6 @@ module.exports = {
}, },
], ],
}, },
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{ {
test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/, test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/,
type: 'asset/resource', type: 'asset/resource',

Loading…
Cancel
Save