Skip to content

Commit

Permalink
feat: Migrate module build to vite
Browse files Browse the repository at this point in the history
* Webpack emitted invalid ES module code, as it still contained `require` calls which
  are undefined on ES modules
* Build time is much shorter
* Built assets are much smaller (570 kB vs 930 kB)
* Remove unneeded import

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Jul 4, 2023
1 parent 687e1f8 commit 3d4d747
Show file tree
Hide file tree
Showing 13 changed files with 2,150 additions and 1,078 deletions.
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ module.exports = {
plugins: [
'cypress',
],
parserOptions: {
babelOptions: {
plugins: [
'@babel/plugin-syntax-import-assertions',
],
},
},
}
File renamed without changes.
4 changes: 2 additions & 2 deletions build/usernameToColor-export.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const snapshot = require('./../src/functions/usernameToColor/__snapshots__/usernameToColor.spec.js.snap')
const result = {}
Object.keys(snapshot).map((key) => {
const uid = key.replace('usernameToColor ', '').replace(' has the proper color 1', '')
result[uid] = JSON.parse(snapshot[key])
const uid = key.replace('usernameToColor ', '').replace(' has the proper color 1', '')
result[uid] = JSON.parse(snapshot[key])
})
console.log(JSON.stringify(result))
15 changes: 8 additions & 7 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { defineConfig } from 'cypress'
import { DefinePlugin } from 'webpack'
import getCompareSnapshotsPlugin from 'cypress-visual-regression/dist/plugin'
import webpack from 'webpack'
import getCompareSnapshotsPlugin from 'cypress-visual-regression/dist/plugin.js'
import path from 'path'
import webpackConfig from '@nextcloud/webpack-vue-config'
import webpackRules from '@nextcloud/webpack-vue-config/rules'
import webpackRules from '@nextcloud/webpack-vue-config/rules.js'

import { loadTranslations } from './resources/translations'
import { loadTranslations } from './build/translations.js'

const SCOPE_VERSION = Date.now()
webpackRules.RULE_SCSS.use.push({
const SCOPE_VERSION = Date.now();

(webpackRules.RULE_SCSS.use as webpack.RuleSetUse[]).push({
loader: 'sass-loader',
options: {
additionalData: `@use 'sass:math'; $scope_version:${SCOPE_VERSION}; @import 'variables'; @import 'material-icons';`,
Expand Down Expand Up @@ -72,7 +73,7 @@ export default defineConfig({
bundler: 'webpack',
webpackConfig: async () => {
const translations = await loadTranslations(path.resolve(__dirname, './l10n'))
webpackConfig.plugins.push(new DefinePlugin({
webpackConfig.plugins.push(new webpack.DefinePlugin({
PRODUCTION: false,
SCOPE_VERSION,
TRANSLATIONS: JSON.stringify(translations),
Expand Down
2 changes: 1 addition & 1 deletion cypress/visual/NcAppSidebar/NcAppSidebar-compact.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import BuildAppSidebarTest from './NcAppSidebarMixin'
import BuildAppSidebarTest from './NcAppSidebarMixin.js'

BuildAppSidebarTest(true)
2 changes: 1 addition & 1 deletion cypress/visual/NcAppSidebar/NcAppSidebar.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import BuildAppSidebarTest from './NcAppSidebarMixin'
import BuildAppSidebarTest from './NcAppSidebarMixin.js'

BuildAppSidebarTest(false)
3,067 changes: 2,031 additions & 1,036 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
"scripts": {
"dev": "webpack --node-env development --progress",
"watch": "webpack --node-env development --progress --watch",
"watch:module": "LIBRARY_TARGET=module webpack --node-env development --progress --watch",
"watch:module": "vite build --mode development --watch",
"build": "webpack --node-env production --progress && npm run build:module",
"build:module": "LIBRARY_TARGET=module webpack --node-env production --progress",
"build:module": "vite --mode production build",
"l10n:extract": "node build/extract-l10n.js",
"lint": "eslint --ext .js,.vue src",
"lint:fix": "eslint --ext .js,.vue src --fix",
Expand All @@ -31,8 +31,14 @@
"cypress:gui": "TZ=UTC cypress open --component",
"cypress:update-snapshots": "TZ=UTC cypress run --component --spec cypress/visual/**/*.cy.js --env type=base --config screenshotsFolder=cypress/snapshots/base"
},
"main": "dist/ncvuecomponents.js",
"module": "dist/index.module.js",
"main": "dist/index.js",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./dist/": "./dist/"
},
"files": [
"CHANGELOG.md",
"LICENSE",
Expand Down Expand Up @@ -87,6 +93,7 @@
"npm": "^9.0.0"
},
"devDependencies": {
"@babel/plugin-syntax-import-assertions": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@cypress/vue2": "^2.0.1",
"@fontsource/roboto": "^5.0.0",
Expand All @@ -96,6 +103,7 @@
"@nextcloud/eslint-config": "^8.3.0-beta.0",
"@nextcloud/stylelint-config": "^2.3.0",
"@nextcloud/webpack-vue-config": "github:nextcloud/webpack-vue-config#master",
"@susnux/nextcloud-vite-config": "^1.0.0-beta.13",
"@vue/test-utils": "^1.3.0",
"@vue/tsconfig": "^0.4.0",
"@vue/vue2-jest": "^29.0.0",
Expand All @@ -117,9 +125,11 @@
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
"url-loader": "^4.1.1",
"vite": "^4.3.9",
"vue-eslint-parser": "^9.0.3",
"vue-styleguidist": "~4.72.0",
"vue-template-compiler": "^2.7.14",
"webpack": "^5.88.1",
"webpack-merge": "^5.9.0",
"webpack-node-externals": "^3.0.0"
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/NcDatetimePicker/index.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
$cell_height: 32px;

@import '~vue2-datepicker/scss/index';
@import 'vue2-datepicker/scss/index';

.mx-datepicker[data-v-#{$scope_version}] {
user-select: none;
Expand Down
2 changes: 1 addition & 1 deletion src/components/NcEmojiPicker/NcEmojiPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export default {
</script>

<style lang="scss">
@import '~emoji-mart-vue-fast/css/emoji-mart.css';
@import 'emoji-mart-vue-fast/css/emoji-mart.css';

.emoji-mart {
background-color: var(--color-main-background) !important;
Expand Down
4 changes: 1 addition & 3 deletions src/utils/focusTrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// eslint-disable-next-line import/named
import { FocusTrap } from 'focus-trap'

/**
* Return the default global focus trap stack
*
* @return {FocusTrap[]}
* @return {import('focus-trap').FocusTrap[]}
*/
export const getTrapStack = function() {
// Create global stack if undefined
Expand Down
79 changes: 79 additions & 0 deletions vite.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import type { Plugin } from 'vite'
import { createLibConfig } from '@susnux/nextcloud-vite-config'
import { resolve } from 'path'
import { defineConfig } from 'vite'

import md5 from 'md5'
import * as url from 'url'

import { loadTranslations } from './build/translations.js'

// `__dirname` not available on ES modules by default
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))

const appVersion = JSON.stringify(process.env.npm_package_version || 'nextcloud-vue')
const SCOPE_VERSION = md5(appVersion).slice(0, 7) as string
const TRANSLATIONS = await loadTranslations(resolve(__dirname, './l10n'))

// Entry points which we build using vite
const entryPoints = {
index: resolve(__dirname, 'src/index.js'),
}

// Plugin for stripping out <docs> sections from vue files
const vueDocsPlugin: Plugin = {
name: 'vue-docs-plugin',
transform(code, id) {
if (!/vue&type=doc/.test(id)) {
return
}
return 'export default ""'
},
}

// Customizations for the vite config
const overrides = defineConfig({
build: {
// Vite is run second so do not remove webpack files
emptyOutDir: false,
},
plugins: [
vueDocsPlugin,
],
css: {
devSourcemap: true,
preprocessorOptions: {
scss: {
additionalData: `@use 'sass:math'; $scope_version:${SCOPE_VERSION}; @import 'variables'; @import 'material-icons';`,
sourceMapContents: false,
includePaths: [
resolve(__dirname, 'src/assets'),
],
},
},
},
})

// We need a callback config so we can access the vite build mode
export default defineConfig((env) => {

const createConfig = createLibConfig(entryPoints, {
// Add our overrides to the config
config: overrides,
// Packages with paths imports should be added here to mark them as external as well
nodeExternalsOptions: {
include: [/^vue-material-design-icons\//, /^@nextcloud\/l10n\//, /^@mdi\/svg\//],
},
// For backwards compatibility we include the css within the js files
inlineCSS: true,
// Disable polyfills
coreJS: false,
replace: {
PRODUCTION: JSON.stringify(env.mode === 'production'),
SCOPE_VERSION,
TRANSLATIONS: ';' + JSON.stringify(TRANSLATIONS),
},
})

return createConfig(env)
})
26 changes: 4 additions & 22 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ const path = require('path')
const { DefinePlugin } = require('webpack')
const BabelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
const nodeExternals = require('webpack-node-externals')
const { loadTranslations } = require('./build/translations.js')

const buildMode = process.env.NODE_ENV
const isDev = buildMode === 'development'
const libraryTarget = process.env.LIBRARY_TARGET ?? 'umd'

const { loadTranslations } = require('./resources/translations.js')
const { dependencies } = require('./package.json')

// scope variable
// fallback for cypress testing
Expand All @@ -26,7 +23,7 @@ console.info('This build version hash is', versionHash, '\n')

webpackConfig.entry = {
install: path.join(__dirname, 'src', 'install.js'),
ncvuecomponents: path.join(__dirname, 'src', 'index.js'),
index: path.join(__dirname, 'src', 'index.js'),

...globSync('src/components/*/index.js').reduce((acc, item) => {
const name = item
Expand Down Expand Up @@ -67,7 +64,7 @@ webpackConfig.output = {
publicPath: '/dist/',
filename: '[name].js',
library: {
type: libraryTarget,
type: 'umd',
name: ['NextcloudVue', '[name]'],
},
umdNamedDefine: true,
Expand Down Expand Up @@ -115,7 +112,7 @@ webpackRules.RULE_NODE_MJS = {
include: /node_modules/,
type: 'javascript/auto',
resolve: {
fullySpecified: false
fullySpecified: false,
}
}

Expand All @@ -130,20 +127,5 @@ module.exports = async () => {
TRANSLATIONS: JSON.stringify(translations),
}))

if (libraryTarget !== 'umd') {
webpackConfig.experiments = {
outputModule: true,
}

webpackConfig.entry = {
index: path.join(__dirname, 'src', 'index.js'),
}
webpackConfig.output.filename = `[name].${libraryTarget}.js`

webpackConfig.externals = [...webpackConfig.externals, ...Object.keys(dependencies)]

delete webpackConfig.output.library.name
}

return webpackConfig
}

0 comments on commit 3d4d747

Please sign in to comment.