This saves around 3 MB binary size by not including useless fomantic files in the build. Also, this allows us to move jQuery into the main bundle as well which eliminates a few HTTP requests. Also included are webpack config changes: - split less and css loaders to speed up compliation - enable css sourcemaps - switch css minfier plugin to cssnano-webpack-plugin which works better for sourcemaps than the previous plugin Co-authored-by: techknowlogick <techknowlogick@gitea.io>tags/v1.13.0-rc1
/public/serviceworker.js | /public/serviceworker.js | ||||
/public/css | /public/css | ||||
/public/fonts | /public/fonts | ||||
/public/fomantic | |||||
/public/img/svg | /public/img/svg | ||||
/web_src/fomantic/build | |||||
/VERSION | /VERSION | ||||
# Snapcraft | # Snapcraft |
GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list -mod=vendor ./... | grep -v /vendor/))) | GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list -mod=vendor ./... | grep -v /vendor/))) | ||||
WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f) | |||||
WEBPACK_SOURCES := $(shell find web_src -type f) | |||||
WEBPACK_CONFIGS := webpack.config.js | WEBPACK_CONFIGS := webpack.config.js | ||||
WEBPACK_DEST := public/js/index.js public/css/index.css | WEBPACK_DEST := public/js/index.js public/css/index.css | ||||
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/serviceworker.js public/img/svg | WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/serviceworker.js public/img/svg | ||||
GO_SOURCES_OWN := $(filter-out vendor/% %/bindata.go, $(GO_SOURCES)) | GO_SOURCES_OWN := $(filter-out vendor/% %/bindata.go, $(GO_SOURCES)) | ||||
FOMANTIC_CONFIGS := semantic.json web_src/fomantic/theme.config.less web_src/fomantic/_site/globals/site.variables | FOMANTIC_CONFIGS := semantic.json web_src/fomantic/theme.config.less web_src/fomantic/_site/globals/site.variables | ||||
FOMANTIC_DEST := public/fomantic/semantic.min.js public/fomantic/semantic.min.css | |||||
FOMANTIC_DEST_DIR := public/fomantic | |||||
FOMANTIC_DEST := web_src/fomantic/build/semantic.js web_src/fomantic/build/semantic.css | |||||
FOMANTIC_DEST_DIR := web_src/fomantic/build | |||||
#To update swagger use: GO111MODULE=on go get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.20.1 | #To update swagger use: GO111MODULE=on go get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.20.1 | ||||
SWAGGER := $(GO) run -mod=vendor github.com/go-swagger/go-swagger/cmd/swagger | SWAGGER := $(GO) run -mod=vendor github.com/go-swagger/go-swagger/cmd/swagger | ||||
npx stylelint web_src/less | npx stylelint web_src/less | ||||
.PHONY: watch-frontend | .PHONY: watch-frontend | ||||
watch-frontend: node_modules | |||||
watch-frontend: node-check $(FOMANTIC_DEST) node_modules | |||||
rm -rf $(WEBPACK_DEST_ENTRIES) | rm -rf $(WEBPACK_DEST_ENTRIES) | ||||
NODE_ENV=development npx webpack --hide-modules --display-entrypoints=false --watch --progress | NODE_ENV=development npx webpack --hide-modules --display-entrypoints=false --watch --progress | ||||
.PHONY: fomantic | .PHONY: fomantic | ||||
fomantic: $(FOMANTIC_DEST) | fomantic: $(FOMANTIC_DEST) | ||||
$(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) package-lock.json | node_modules | |||||
$(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) | node_modules | |||||
rm -rf $(FOMANTIC_DEST_DIR) | rm -rf $(FOMANTIC_DEST_DIR) | ||||
cp web_src/fomantic/theme.config.less node_modules/fomantic-ui/src/theme.config | cp web_src/fomantic/theme.config.less node_modules/fomantic-ui/src/theme.config | ||||
cp -r web_src/fomantic/_site/* node_modules/fomantic-ui/src/_site/ | cp -r web_src/fomantic/_site/* node_modules/fomantic-ui/src/_site/ |
// KnownPublicEntries list all direct children in the `public` directory | // KnownPublicEntries list all direct children in the `public` directory | ||||
var KnownPublicEntries = []string{ | var KnownPublicEntries = []string{ | ||||
"css", | "css", | ||||
"fomantic", | |||||
"img", | "img", | ||||
"js", | "js", | ||||
"serviceworker.js", | "serviceworker.js", |
"resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", | "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", | ||||
"integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==" | "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==" | ||||
}, | }, | ||||
"cssnano-webpack-plugin": { | |||||
"version": "1.0.3", | |||||
"resolved": "https://registry.npmjs.org/cssnano-webpack-plugin/-/cssnano-webpack-plugin-1.0.3.tgz", | |||||
"integrity": "sha512-OkxkOR6WlTBdIbPObCTWuUuZCr3bDPYClm5gquo2LEkOCvM1mbI9MAUstqS2+u6pImnd2f6dNgmmcvVbmYJ7fg==", | |||||
"requires": { | |||||
"cssnano": "^4.1.10", | |||||
"webpack-sources": "^1.4.3" | |||||
} | |||||
}, | |||||
"csso": { | "csso": { | ||||
"version": "4.0.3", | "version": "4.0.3", | ||||
"resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", | "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", | ||||
"integrity": "sha512-eYboRV94Vco725nKMlpkn3nV2+96p9c3gKXRsYqAJSswSENvBhN7n5L+uDhY58xQa0UukWsDMTGELzmD8Q+wTA==", | "integrity": "sha512-eYboRV94Vco725nKMlpkn3nV2+96p9c3gKXRsYqAJSswSENvBhN7n5L+uDhY58xQa0UukWsDMTGELzmD8Q+wTA==", | ||||
"dev": true | "dev": true | ||||
}, | }, | ||||
"last-call-webpack-plugin": { | |||||
"version": "3.0.0", | |||||
"resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", | |||||
"integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", | |||||
"requires": { | |||||
"lodash": "^4.17.5", | |||||
"webpack-sources": "^1.1.0" | |||||
} | |||||
}, | |||||
"last-run": { | "last-run": { | ||||
"version": "1.1.1", | "version": "1.1.1", | ||||
"resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", | "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", | ||||
"mimic-fn": "^1.0.0" | "mimic-fn": "^1.0.0" | ||||
} | } | ||||
}, | }, | ||||
"optimize-css-assets-webpack-plugin": { | |||||
"version": "5.0.3", | |||||
"resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", | |||||
"integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", | |||||
"requires": { | |||||
"cssnano": "^4.1.10", | |||||
"last-call-webpack-plugin": "^3.0.0" | |||||
} | |||||
}, | |||||
"optionator": { | "optionator": { | ||||
"version": "0.9.1", | "version": "0.9.1", | ||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", | ||||
"version": "4.0.2", | "version": "4.0.2", | ||||
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", | "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", | ||||
"integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", | "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", | ||||
"dev": true, | |||||
"requires": { | "requires": { | ||||
"postcss": "^7.0.26" | "postcss": "^7.0.26" | ||||
} | } |
"clipboard": "2.0.6", | "clipboard": "2.0.6", | ||||
"core-js": "3.6.5", | "core-js": "3.6.5", | ||||
"css-loader": "3.5.3", | "css-loader": "3.5.3", | ||||
"cssnano": "4.1.10", | |||||
"cssnano-webpack-plugin": "1.0.3", | |||||
"domino": "2.1.5", | "domino": "2.1.5", | ||||
"dropzone": "5.7.1", | "dropzone": "5.7.1", | ||||
"fast-glob": "3.2.2", | "fast-glob": "3.2.2", | ||||
"mini-css-extract-plugin": "0.9.0", | "mini-css-extract-plugin": "0.9.0", | ||||
"monaco-editor": "0.20.0", | "monaco-editor": "0.20.0", | ||||
"monaco-editor-webpack-plugin": "1.9.0", | "monaco-editor-webpack-plugin": "1.9.0", | ||||
"optimize-css-assets-webpack-plugin": "5.0.3", | |||||
"postcss-loader": "3.0.0", | "postcss-loader": "3.0.0", | ||||
"postcss-preset-env": "6.7.0", | "postcss-preset-env": "6.7.0", | ||||
"postcss-safe-parser": "4.0.2", | |||||
"svg-sprite-loader": "5.0.0", | "svg-sprite-loader": "5.0.0", | ||||
"svgo": "1.3.2", | "svgo": "1.3.2", | ||||
"svgo-loader": "2.2.1", | "svgo-loader": "2.2.1", |
"themes": "src/themes/" | "themes": "src/themes/" | ||||
}, | }, | ||||
"output": { | "output": { | ||||
"packaged": "../../public/fomantic/", | |||||
"uncompressed": "../../public/fomantic/components/", | |||||
"compressed": "../../public/fomantic/components/", | |||||
"themes": "../../public/fomantic/themes/" | |||||
"packaged": "../../web_src/fomantic/build/", | |||||
"uncompressed": "../../web_src/fomantic/build/components/", | |||||
"compressed": "../../web_src/fomantic/build/components/", | |||||
"themes": "../../web_src/fomantic/build/themes/" | |||||
}, | }, | ||||
"clean": "../../public/fomantic/" | |||||
"clean": "../../web_src/fomantic/build/" | |||||
}, | }, | ||||
"permission": false, | "permission": false, | ||||
"autoInstall": false, | "autoInstall": false, |
{{template "custom/body_outer_post" .}} | {{template "custom/body_outer_post" .}} | ||||
{{template "base/footer_content" .}} | {{template "base/footer_content" .}} | ||||
<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script> | |||||
{{if .RequireSimpleMDE}} | {{if .RequireSimpleMDE}} | ||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script> | <script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script> | ||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script> | <script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script> | ||||
{{end}} | {{end}} | ||||
<!-- Third-party libraries --> | <!-- Third-party libraries --> | ||||
{{if .RequireMinicolors}} | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script> | |||||
{{end}} | |||||
{{if .RequireU2F}} | {{if .RequireU2F}} | ||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js"></script> | <script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js"></script> | ||||
{{end}} | {{end}} | ||||
<script src='{{ URLJoin .RecaptchaURL "api.js"}}' async></script> | <script src='{{ URLJoin .RecaptchaURL "api.js"}}' async></script> | ||||
{{end}} | {{end}} | ||||
{{end}} | {{end}} | ||||
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script> | |||||
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script> | <script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script> | ||||
{{if .RequireMinicolors}} | |||||
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script> | |||||
{{end}} | |||||
{{template "custom/footer" .}} | {{template "custom/footer" .}} | ||||
</body> | </body> | ||||
</html> | </html> |
{{if .RequireSimpleMDE}} | {{if .RequireSimpleMDE}} | ||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css"> | <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css"> | ||||
{{end}} | {{end}} | ||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}"> | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}"> | <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}"> | ||||
<noscript> | <noscript> | ||||
<style> | <style> |
const cssnano = require('cssnano'); | |||||
const fastGlob = require('fast-glob'); | const fastGlob = require('fast-glob'); | ||||
const wrapAnsi = require('wrap-ansi'); | const wrapAnsi = require('wrap-ansi'); | ||||
const CssNanoPlugin = require('cssnano-webpack-plugin'); | |||||
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); | const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); | ||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | ||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); | |||||
const PostCSSPresetEnv = require('postcss-preset-env'); | const PostCSSPresetEnv = require('postcss-preset-env'); | ||||
const PostCSSSafeParser = require('postcss-safe-parser'); | |||||
const SpriteLoaderPlugin = require('svg-sprite-loader/plugin'); | const SpriteLoaderPlugin = require('svg-sprite-loader/plugin'); | ||||
const TerserPlugin = require('terser-webpack-plugin'); | const TerserPlugin = require('terser-webpack-plugin'); | ||||
const VueLoaderPlugin = require('vue-loader/lib/plugin'); | const VueLoaderPlugin = require('vue-loader/lib/plugin'); | ||||
const isProduction = process.env.NODE_ENV !== 'development'; | const isProduction = process.env.NODE_ENV !== 'development'; | ||||
const filterCssImport = (parsedImport, cssFile) => { | |||||
const url = parsedImport && parsedImport.url ? parsedImport.url : parsedImport; | |||||
const importedFile = url.replace(/[?#].+/, '').toLowerCase(); | |||||
if (cssFile.includes('monaco')) return true; | |||||
if (cssFile.includes('fomantic')) { | |||||
if (/brand-icons/.test(importedFile)) return false; | |||||
if (/(eot|ttf|woff)$/.test(importedFile)) return false; | |||||
return true; | |||||
} | |||||
return cssFile.includes('node_modules'); | |||||
}; | |||||
module.exports = { | module.exports = { | ||||
mode: isProduction ? 'production' : 'development', | mode: isProduction ? 'production' : 'development', | ||||
entry: { | entry: { | ||||
index: [ | index: [ | ||||
resolve(__dirname, 'web_src/js/jquery.js'), | |||||
resolve(__dirname, 'web_src/fomantic/build/semantic.js'), | |||||
resolve(__dirname, 'web_src/js/index.js'), | resolve(__dirname, 'web_src/js/index.js'), | ||||
resolve(__dirname, 'web_src/fomantic/build/semantic.css'), | |||||
resolve(__dirname, 'web_src/less/index.less'), | resolve(__dirname, 'web_src/less/index.less'), | ||||
], | ], | ||||
swagger: [ | swagger: [ | ||||
resolve(__dirname, 'web_src/js/standalone/swagger.js'), | resolve(__dirname, 'web_src/js/standalone/swagger.js'), | ||||
], | ], | ||||
jquery: [ | |||||
resolve(__dirname, 'web_src/js/jquery.js'), | |||||
], | |||||
serviceworker: [ | serviceworker: [ | ||||
resolve(__dirname, 'web_src/js/serviceworker.js'), | resolve(__dirname, 'web_src/js/serviceworker.js'), | ||||
], | ], | ||||
}, | }, | ||||
}, | }, | ||||
}), | }), | ||||
new OptimizeCSSAssetsPlugin({ | |||||
cssProcessor: cssnano, | |||||
cssProcessorOptions: { | |||||
parser: PostCSSSafeParser, | |||||
}, | |||||
cssProcessorPluginOptions: { | |||||
new CssNanoPlugin({ | |||||
sourceMap: true, | |||||
cssnanoOptions: { | |||||
preset: [ | preset: [ | ||||
'default', | 'default', | ||||
{ | { | ||||
monaco: { | monaco: { | ||||
test: /monaco-editor/, | test: /monaco-editor/, | ||||
name: 'monaco', | name: 'monaco', | ||||
chunks: 'async' | |||||
} | |||||
} | |||||
} | |||||
chunks: 'async', | |||||
}, | |||||
}, | |||||
}, | |||||
}, | }, | ||||
module: { | module: { | ||||
rules: [ | rules: [ | ||||
], | ], | ||||
'@babel/plugin-proposal-object-rest-spread', | '@babel/plugin-proposal-object-rest-spread', | ||||
], | ], | ||||
generatorOpts: { | |||||
compact: false, | |||||
}, | |||||
}, | }, | ||||
}, | }, | ||||
], | ], | ||||
}, | }, | ||||
{ | { | ||||
test: /\.(less|css)$/i, | |||||
test: /.css$/i, | |||||
use: [ | |||||
{ | |||||
loader: MiniCssExtractPlugin.loader, | |||||
}, | |||||
{ | |||||
loader: 'css-loader', | |||||
options: { | |||||
importLoaders: 1, | |||||
url: filterCssImport, | |||||
import: filterCssImport, | |||||
sourceMap: true, | |||||
}, | |||||
}, | |||||
{ | |||||
loader: 'postcss-loader', | |||||
options: { | |||||
plugins: () => [ | |||||
PostCSSPresetEnv(), | |||||
], | |||||
sourceMap: true, | |||||
}, | |||||
}, | |||||
], | |||||
}, | |||||
{ | |||||
test: /.less$/i, | |||||
use: [ | use: [ | ||||
{ | { | ||||
loader: MiniCssExtractPlugin.loader, | loader: MiniCssExtractPlugin.loader, | ||||
loader: 'css-loader', | loader: 'css-loader', | ||||
options: { | options: { | ||||
importLoaders: 2, | importLoaders: 2, | ||||
url: (_url, resourcePath) => { | |||||
// only resolve URLs for dependencies | |||||
return resourcePath.includes('node_modules'); | |||||
}, | |||||
} | |||||
url: filterCssImport, | |||||
import: filterCssImport, | |||||
sourceMap: true, | |||||
}, | |||||
}, | }, | ||||
{ | { | ||||
loader: 'postcss-loader', | loader: 'postcss-loader', | ||||
plugins: () => [ | plugins: () => [ | ||||
PostCSSPresetEnv(), | PostCSSPresetEnv(), | ||||
], | ], | ||||
sourceMap: true, | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
loader: 'less-loader', | loader: 'less-loader', | ||||
options: { | |||||
sourceMap: true, | |||||
}, | |||||
}, | }, | ||||
], | ], | ||||
}, | }, | ||||
chunkFilename: 'css/[name].css', | chunkFilename: 'css/[name].css', | ||||
}), | }), | ||||
new SourceMapDevToolPlugin({ | new SourceMapDevToolPlugin({ | ||||
filename: 'js/[name].js.map', | |||||
filename: '[file].map', | |||||
include: [ | include: [ | ||||
'js/index.js', | 'js/index.js', | ||||
'css/index.css', | |||||
], | ], | ||||
}), | }), | ||||
new SpriteLoaderPlugin({ | new SpriteLoaderPlugin({ | ||||
modulesDirectories: [ | modulesDirectories: [ | ||||
resolve(__dirname, 'node_modules'), | resolve(__dirname, 'node_modules'), | ||||
], | ], | ||||
additionalModules: [ | |||||
{ | |||||
name: 'fomantic-ui', | |||||
directory: resolve(__dirname, 'node_modules/fomantic-ui'), | |||||
}, | |||||
], | |||||
renderLicenses: (modules) => { | renderLicenses: (modules) => { | ||||
const line = '-'.repeat(80); | const line = '-'.repeat(80); | ||||
return modules.map((module) => { | return modules.map((module) => { |