How do I remove vue spec files from vite config - javascript

I've succesfully added vite to my project. It builds fine for prodiction. However in Production I have an error
Uncaught ReferenceError: describe is not defined
at index.ba9d79ff.js:1119:1426
I then saw the my .spec files where being added. I thought vite would of handled the removal of the test files. I want to remove my .spec files from production.
but not having such luck. I'm using Vue 2 with vite. I added
production: {
exclude: ['src/components/**/*.{spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']
},
but the files are still being added. Is there something more I need to do?
My config
import { defineConfig } from "vite";
import { createVuePlugin as vue } from "vite-plugin-vue2";
import { VuetifyResolver } from "unplugin-vue-components/resolvers";
import Components from "unplugin-vue-components/vite";
// https://vitejs.dev/config/const
const path = require("path");
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [
// Vuetify
VuetifyResolver(),
],
}),
],
resolve: {
extensions: [
".mjs",
".js",
".ts",
".jsx",
".tsx",
".json",
".vue",
".scss",
],
alias: {
"#": path.resolve(__dirname, "./src"),
json2csv: "json2csv/dist/json2csv.umd.js",
"~bootstrap": "bootstrap",
},
},
production: {
exclude: ['src/components/**/*.{spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']
},
extensions: etc,
css: {
preprocessorOptions: {
scss: {
// additionalData: `#import "src/scss/app.scss";`,
// additionalData: `#import "src/scss/_variables.scss";`,
sourceMap: false,
additionalData(source, fp) {
// All scss files ending with imports.scss
// will not re-import additionalData
if (fp.endsWith("_variables.scss")) return source;
// Use additionalData from legacy nuxt scss options
// return `#import "#/assets/mixin.scss"; ${source}`;
return `#import "src/scss/_variables.scss"; ${source}`;
},
},
},
},
server: {
port: 8090,
},
});

Related

Huge chunk sizes due to dynamic json imports in production build

I have a vite SPA and use dynamic imports to load my json files. Since I need to load numerous very large json files, the index.js file in my /dist becomes too big in my production build.
What is the best way to import these json files dynamically but still keep small chunks? Can I import somehow the json files dynamically as own chunks, similar to images and videos with hashes?
Here my vite.config.js
import path from 'path'
import { defineConfig } from 'vite'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
import { createHtmlPlugin } from 'vite-plugin-html'
import svgr from 'vite-plugin-svgr'
import legacy from '#vitejs/plugin-legacy'
import react from '#vitejs/plugin-react'
import { name } from './package.json'
export default defineConfig({
base: '/widgets/' + name + '/',
server: {
open: true, // Define a BROWSER in your .env-File to specify which browser. Defaults to Chrome. https://vitejs.dev/config/#server-open
port: 3000,
},
resolve: {
alias: {
'#Assets': path.resolve(__dirname, 'src/assets'),
'#Components': path.resolve(__dirname, 'src/components'),
'#Examples': path.resolve(__dirname, 'src/examples'),
'#Scripts': path.resolve(__dirname, 'src/scripts'),
'#Styles': path.resolve(__dirname, 'src/assets/styles'),
'#Cms': path.resolve(__dirname, 'src/assets/styles/cms'),
},
},
css: {
devSourcemap: true, // needed for css imported in cms template
},
define: {
__DATA_PATH__: JSON.stringify(process.env.npm_package_config_dataPath),
},
build: {
rollupOptions: {
output: {
entryFileNames: `[name].js`,
chunkFileNames: `[name].js`,
assetFileNames: `[name].[ext]`,
},
},
},
plugins: [
legacy({
polyfills: true,
}),
react(),
createHtmlPlugin({
minify: true,
inject: {
data: {
title: name,
id: name,
},
},
}),
cssInjectedByJsPlugin(),
svgr(),
],
})
You can try this configuration:
// vite.config.ts
build: {
chunkSizeWarningLimit: 500, // default 500 KB
},
https://vitejs.dev/config/build-options.html#build-chunksizewarninglimit

migrate from webpack to vite with vuejs for chrome extension project

I am working on a chrome extension using vuejs currently i have a ready project to start with but it is with webpack.
In the webpack I have multi-entry points some of which lead to generating HTML files and others with javascript only.
with webpack it is clear what is the inputs and how they will be as output in Vite i tried but there is a lot of plugins outdated that work with vuejs 3
this link contains the project
https://stackblitz.com/edit/vue-v83gga
my webpack file is :
const path = require("path");
const fs = require("fs");
// Generate pages object
const pages = {};
function getEntryFile(entryPath) {
let files = fs.readdirSync(entryPath);
return files;
}
const chromeName = getEntryFile(path.resolve(`src/entry`));
function getFileExtension(filename) {
return /[.]/.exec(filename) ? /[^.]+$/.exec(filename)[0] : undefined;
}
chromeName.forEach((name) => {
const fileExtension = getFileExtension(name);
const fileName = name.replace("." + fileExtension, "");
pages[fileName] = {
entry: `src/entry/${name}`,
template: "public/index.html",
filename: `${fileName}.html`,
};
});
const isDevMode = process.env.NODE_ENV === "development";
module.exports = {
pages,
filenameHashing: false,
chainWebpack: (config) => {
config.plugin("copy").use(require("copy-webpack-plugin"), [
{
patterns: [
{
from: path.resolve(`src/manifest.${process.env.NODE_ENV}.json`),
to: `${path.resolve("dist")}/manifest.json`,
},
{
from: path.resolve(`public/`),
to: `${path.resolve("dist")}/`,
},
],
},
]);
},
configureWebpack: {
output: {
filename: `[name].js`,
chunkFilename: `[name].js`,
},
devtool: isDevMode ? "inline-source-map" : false,
},
css: {
extract: false, // Make sure the css is the same
},
};
i finally find out a solution for it as a pre-build template by vitesse written with typescript
https://github.com/antfu/vitesse-webext
in short answer if you want to have multiple entries of HTML files you can add them to the original vite.config.js file
regarding the content.ts file, it needs a different vite.config.content.ts file and we have to call it when we build the project like this
vite build && vite build --config vite.config.content.ts
regarding the vite.config.ts file, the code will be like this written in typescript
/// <reference types="vitest" />
import { dirname, relative } from 'path'
import type { UserConfig } from 'vite'
import { defineConfig } from 'vite'
import Vue from '#vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import WindiCSS from 'vite-plugin-windicss'
import windiConfig from './windi.config'
import { isDev, port, r } from './scripts/utils'
export const sharedConfig: UserConfig = {
root: r('src'),
resolve: {
alias: {
'~/': `${r('src')}/`,
},
},
define: {
__DEV__: isDev,
},
plugins: [
Vue(),
AutoImport({
imports: [
'vue',
{
'webextension-polyfill': [
['*', 'browser'],
],
},
],
dts: r('src/auto-imports.d.ts'),
}),
// https://github.com/antfu/unplugin-vue-components
Components({
dirs: [r('src/components')],
// generate `components.d.ts` for ts support with Volar
dts: r('src/components.d.ts'),
resolvers: [
// auto import icons
IconsResolver({
componentPrefix: '',
}),
],
}),
// https://github.com/antfu/unplugin-icons
Icons(),
// rewrite assets to use relative path
{
name: 'assets-rewrite',
enforce: 'post',
apply: 'build',
transformIndexHtml(html, { path }) {
return html.replace(/"\/assets\//g, `"${relative(dirname(path), '/assets')}/`)
},
},
],
optimizeDeps: {
include: [
'vue',
'#vueuse/core',
'webextension-polyfill',
],
exclude: [
'vue-demi',
],
},
}
export default defineConfig(({ command }) => ({
...sharedConfig,
base: command === 'serve' ? `http://localhost:${port}/` : '/dist/',
server: {
port,
hmr: {
host: 'localhost',
},
},
build: {
outDir: r('extension/dist'),
emptyOutDir: false,
sourcemap: isDev ? 'inline' : false,
// https://developer.chrome.com/docs/webstore/program_policies/#:~:text=Code%20Readability%20Requirements
terserOptions: {
mangle: false,
},
rollupOptions: {
input: {
background: r('src/background/index.html'),
options: r('src/options/index.html'),
popup: r('src/popup/index.html'),
},
},
},
plugins: [
...sharedConfig.plugins!,
// https://github.com/antfu/vite-plugin-windicss
WindiCSS({
config: windiConfig,
}),
],
test: {
globals: true,
environment: 'jsdom',
},
}))
the important part of it is this
vite.config.ts
...
build: {
outDir: r('extension/dist'),
emptyOutDir: false,
sourcemap: isDev ? 'inline' : false,
// https://developer.chrome.com/docs/webstore/program_policies/#:~:text=Code%20Readability%20Requirements
terserOptions: {
mangle: false,
},
rollupOptions: {
input: {
background: r('src/background/index.html'),
options: r('src/options/index.html'),
popup: r('src/popup/index.html'),
},
},
},
...
Thank you to anyone who tried to help and I hope this will be helpful to others
Regards

Feature files require some loader file to run

I'm trying to run the Feature file using cucumber in Cypress 10.2.0.
It is throwing me an issue of "WebPack Compilation Error"
Error: Webpack Compilation Error
./cypress/e2e/BankManagerLogin.feature 1:14
Module parse failed: Unexpected token (1:14)
You may need an appropriate loader to handle this file type, currently, no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
any help would be appreciated
The cypress.config file needs adjusting to clear that error.
Try this, it's bolier-plate code from the badeball repository.
This assumes you have Typescript (let me know if you're only using Javascript).
import { defineConfig } from "cypress";
import * as webpack from "#cypress/webpack-preprocessor";
import { addCucumberPreprocessorPlugin } from "#badeball/cypress-cucumber-preprocessor";
async function setupNodeEvents(
on: Cypress.PluginEvents,
config: Cypress.PluginConfigOptions
): Promise<Cypress.PluginConfigOptions> {
await addCucumberPreprocessorPlugin(on, config);
on(
"file:preprocessor",
webpack({
webpackOptions: {
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.ts$/,
exclude: [/node_modules/],
use: [
{
loader: "ts-loader",
},
],
},
{
test: /\.feature$/,
use: [
{
loader: "#badeball/cypress-cucumber-preprocessor/webpack",
options: config,
},
],
},
],
},
},
})
);
// Make sure to return the config object as it might have been modified by the plugin.
return config;
}
export default defineConfig({
e2e: {
specPattern: "**/*.feature",
supportFile: false,
setupNodeEvents,
},
});

Rollup - not packaging entire repo (child component missing)

I have a component library written in vue that I am wrapping up with rollup
I am having an issue with mixins not being wrapped up into the final library. Intially i thought that the path was the issue as most of the mixins are local.
Originally:
import mixin from '../../mixins/color'
Repo folder structure
- dist //output
- src //All files related to the actual component within the library
- components
- comps
- alert //general components
- inputs //input components
- layout //layout components /row/col
- mixins
- utilities
- entry.js //rollup points to this
- ... //I used nuxt to develop the components to focus on SSR so there are more folders but are excluded in the rollup process
Apparently native rollup doesn't like indirect imports so I attempted to add rollup-plugin-includepaths. My understanding is that I would need to mention the paths required in the imports to work correctly.
Therefore, I added rollup-plugin-includepaths to rollup.config.js plugins and added the root path and the output director as the options
includePaths({
paths: ['src/components/', 'src/mixins/', 'src/utilities/'],
extensions: ['.js', '.vue']
}),
**this did not work **
I decided to remove all relative imports and create aliases for each required directory. This did not work either
What is happening is all mixins imported into the component and added as mixin: [mixins] //whatever they may be are not included in the compiled product?!?!?!
What am I missing????
// rollup.config.js
import fs from 'fs'
import path from 'path'
import vue from 'rollup-plugin-vue'
import alias from '#rollup/plugin-alias'
import commonjs from '#rollup/plugin-commonjs'
import replace from '#rollup/plugin-replace'
import babel from 'rollup-plugin-babel'
import { terser } from 'rollup-plugin-terser'
import minimist from 'minimist'
import postcss from 'rollup-plugin-postcss'
import includePaths from 'rollup-plugin-includepaths'
import del from 'rollup-plugin-delete'
// Get browserslist config and remove ie from es build targets
const esbrowserslist = fs
.readFileSync('./.browserslistrc')
.toString()
.split('\n')
.filter(entry => entry && entry.substring(0, 2) !== 'ie')
const argv = minimist(process.argv.slice(2))
const projectRoot = path.resolve(__dirname)
const baseConfig = {
input: 'src/entry.js',
plugins: {
preVue: [
alias({
resolve: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
entries: [
{ find: '#', replacement: path.resolve(projectRoot, 'src') },
{
find: '#mixins',
replacement: path.resolve(projectRoot, 'src', 'mixins')
},
{
find: '#comps',
replacement: path.resolve(projectRoot, 'src', 'components', 'comps')
},
{
find: '#inputs',
replacement: path.resolve(
projectRoot,
'src',
'components',
'inputs'
)
},
{
find: '#utilities',
replacement: path.resolve(projectRoot, 'src', 'utilities')
}
]
}),
includePaths({
paths: ['src/components/', 'src/mixins/', 'src/utilities/'],
extensions: ['.js', '.vue']
}),
commonjs(),
postcss()
],
replace: {
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.ES_BUILD': JSON.stringify('false')
},
vue: {
css: false,
template: {
isProduction: true
}
},
babel: {
exclude: 'node_modules/**',
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue']
}
}
}
// ESM/UMD/IIFE shared settings: externals
// Refer to https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
const external = [
// list external dependencies, exactly the way it is written in the import statement.
// eg. 'jquery'
'vue'
]
// UMD/IIFE shared settings: output.globals
// Refer to https://rollupjs.org/guide/en#output-globals for details
const globals = {
// Provide global variable names to replace your external imports
// eg. jquery: '$'
vue: 'Vue'
}
// Customize configs for individual targets
const buildFormats = []
if (!argv.format || argv.format === 'es') {
const esConfig = {
...baseConfig,
external,
output: {
compact: true,
file: 'dist/comps.esm.js',
format: 'esm',
exports: 'named'
},
plugins: [
del({ targets: 'dist/*' }),
replace({
...baseConfig.plugins.replace,
'process.env.ES_BUILD': JSON.stringify('true')
}),
...baseConfig.plugins.preVue,
vue(baseConfig.plugins.vue),
babel({
...baseConfig.plugins.babel,
presets: [
[
'#babel/preset-env',
{
targets: esbrowserslist
}
]
]
})
]
}
buildFormats.push(esConfig)
}
if (!argv.format || argv.format === 'cjs') {
const umdConfig = {
...baseConfig,
external,
output: {
compact: true,
file: 'dist/comps.ssr.js',
format: 'cjs',
name: 'Components',
exports: 'named',
globals
},
plugins: [
replace(baseConfig.plugins.replace),
...baseConfig.plugins.preVue,
vue({
...baseConfig.plugins.vue,
template: {
...baseConfig.plugins.vue.template,
optimizeSSR: true
}
}),
babel(baseConfig.plugins.babel)
]
}
buildFormats.push(umdConfig)
}
if (!argv.format || argv.format === 'iife') {
const unpkgConfig = {
...baseConfig,
external,
output: {
compact: true,
file: 'dist/comps.min.js',
format: 'iife',
name: 'Components',
exports: 'named',
globals
},
plugins: [
replace(baseConfig.plugins.replace),
...baseConfig.plugins.preVue,
vue(baseConfig.plugins.vue),
babel(baseConfig.plugins.babel),
terser({
output: {
ecma: 5
}
})
]
}
buildFormats.push(unpkgConfig)
}
// Export config
export default buildFormats
Update
I moved the imported components out of the mixin and added them directly to the component that included them and got the same result. Therefore, i really have no clue what needs to happen.
TL;DR
None of the child components are being included in the rolled up dist '.js' files
Sometimes it is hard to include what is relevant and the question above is guilty.
The problem is within the larger component I had imported the children lazily
ex:
components:{
comp: ()=>import('comp') ///Does not work
}
changed to your standard
import comp from 'comp'
components:{
comp
}

Dynamically loading an external webpack bundled ngModule as a route handler

We want to divide our large frontend projects into multiple separately deployed projects which are easier to work with. I am trying to include a bundled ngModule to handle a route from within another app. The apps must be ignorant of each other's configuration. The bundles will share some large dependencies(like Angular) via globals. We don't need to shake across the bundles and we may just have to accept some duplicate dependencies.
The root router complains that
Error: No NgModule metadata found for 'TestsetModule'.
which leads me to believe the child module is not being angular compiled on load, or is not registering its module for some reason. I think it may be necessary to manually compile the module, but I'm not sure how to use this https://angular.io/api/core/Compiler#compileModuleAndAllComponentsAsync
The root app loads the child via a route:
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const load = require("little-loader");
const routes: Routes = [
{ path: ``, loadChildren: () => new Promise(function (resolve) {
load('http://localhost:3100/testset-module-bundle.js',(err: any) => {
console.log('global loaded bundle is: ', (<any>global).TestsetModule )
resolve((<any>global).TestsetModule)
}
)
})}
];
export const HostRouting: ModuleWithProviders = RouterModule.forRoot(routes);
I also tried using angular router's string resolution syntax rather than this weird global thing you see but I had similar issues.
Here is the module which is being loaded, very standard except for the global export:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HttpModule } from '#angular/http';
//import { MaterialModule } from '#angular/material';
import { FlexLayoutModule } from '#angular/flex-layout';
import { FormsModule } from '#angular/forms';
import { LoggerModule, Level } from '#churro/ngx-log';
import { FeatureLoggerConfig } from './features/logger/services/feature-logger-config';
import { TestsetComponent } from './features/testset/testset.component';
import { TestsetRouting } from './testset.routing';
#NgModule({
imports: [
CommonModule,
//MaterialModule,
FlexLayoutModule,
HttpModule,
FormsModule,
LoggerModule.forChild({
moduleName: 'Testset',
minLevel: Level.INFO
}),
TestsetRouting,
],
declarations: [TestsetComponent],
providers: [
/* TODO: Providers go here */
]
})
class TestsetModule { }
(<any>global).TestsetModule = TestsetModule
export {TestsetModule as default, TestsetModule};
Here is the webpack configuration of the root bundle. Note the global exports via the poorly named "ProvidePlugin".
const webpack = require('webpack');
const AotPlugin = require('#ngtools/webpack').AotPlugin;
const path = require('path');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const IgnorePlugin = require('webpack/lib/IgnorePlugin');
const PolyfillsPlugin = require('webpack-polyfills-plugin');
const WebpackSystemRegister = require('webpack-system-register');
module.exports = (envOptions) => {
envOptions = envOptions || {};
const config = {
entry: {
'bundle': './root.ts'
},
output: {
libraryTarget: 'umd',
filename: '[name].js',//"bundle.[hash].js",
chunkFilename: '[name]-chunk.js',
path: __dirname
},
externals: {
},
resolve: {
extensions: ['.ts', '.js', '.html'],
},
module: {
rules: [
{ test: /\.html$/, loader: 'raw-loader' },
{ test: /\.css$/, loader: 'raw-loader' },
]
},
devtool: '#source-map',
plugins: [
new webpack.ProvidePlugin({
'angular': '#angular/core',
'ngrouter': '#angular/router',
'ngxlog':'#churro/ngx-log'
})
]
};
config.module.rules.push(
{ test: /\.ts$/, loaders: [
'awesome-typescript-loader',
'angular-router-loader',
'angular2-template-loader',
'source-map-loader'
] }
);
}
return config;
};
And here is the webpack configuration of the child bundle. Note the "externals" which look for angular as a global.
module.exports = (envOptions) => {
envOptions = envOptions || {};
const config = {
entry: {
'testset-module-bundle': './src/index.ts'
},
output: {
//library: 'TestsetModule',
libraryTarget: 'umd',
filename: '[name].js',//"bundle.[hash].js",
chunkFilename: '[name]-chunk.js',
path: path.resolve(__dirname, "dist")
},
externals: {
//expect these to come from the app that imported us
// name to be required : name from global
'angular': '#angular/core',
'ngrouter': '#angular/router',
'ngxlog': '#churro/ngx-log'
},
resolve: {
extensions: ['.ts', '.js', '.html'],
},
module: {
rules: [
{ test: /\.html$/, loader: 'raw-loader' },
{ test: /\.css$/, loader: 'raw-loader' },
]
},
devtool: '#source-map',
plugins: [
]
};
config.module.rules.push(
{ test: /\.ts$/, loaders: [
'awesome-typescript-loader',
'angular-router-loader',
'angular2-template-loader',
'source-map-loader'
] }
);
}
return config;
};
And for good measure here is my tsconfig file which 'awesome-typescript-loader' reads.
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"baseUrl": ".",
"rootDir": "src",
"outDir": "app",
"paths": {
"#capone/*": [
"*"
],
"#angular/*": [
"node_modules/#angular/*"
],
"rxjs/*": [
"node_modules/rxjs/*"
]
}
},
"exclude": ["node_modules", "src/node_modules", "compiled", "src/dev_wrapper_app"],
"angularCompilerOptions": {
"genDir": "./compiled",
"skipMetadataEmit": true
}
}
If you're still reading, awesome. I was able to get this working when both bundles are part of the same webpack config and the child module is just a chunk. Angular is designed to do that. But our use case is to have the children and parent be ignorant of each other until runtime.
As you have mentioned
The apps must be ignorant of each other's configuration.
I had a similar problem in Angular2. I solved it by creating a sub-application. A separate sub-main.browser.ts and index.html file. It had its own dependencies, sharing the same node modules. Both main modules bootstrapping different app-component. We were working on Angular without angular-cli.
In webpack config, I added
entry: {
'polyfills': './src/polyfills.browser.ts',
'main' . : './src/main.browser.aot.ts',
'sub-main' : '/src/sub-main.browser.ts'
},
and a more detailed HtmlWebpackPlugin. In the chunks, we load only modules that will be used in both the app. If we see polyfills is common.
new HtmlWebpackPlugin({
template: 'src/index.html',
title: METADATA.title,
chunksSortMode: 'dependency',
metadata: METADATA,
inject: 'head',
chunks: ['polyfills','main']
}),
new HtmlWebpackPlugin({
template: 'src/index2.html',
title: 'Sub app',
chunksSortMode: 'dependency',
metadata: METADATA,
inject: 'head',
filename: './sub-app.html',
chunks: ['polyfills','sub-main']
}),
The next task was to create separate endpoints for both sub apps for dev environment.
devServer: {
port: METADATA.port,
host: METADATA.host,
historyApiFallback: true,
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
proxy: {
"/sub-app": {
target: "http://localhost:3009",
bypass: function(req, res, proxyOptions) {
return "/index2.html";
}
}
}
},
Now when I build the project two different HTML files are generated. Each with their own javascript bundle dependencies and common assets. They can be deployed on a different server as well.
I was able to finish my POC with lots of trial and error. My suggestion will be to look a step above angular. See how webpack is deploying your current project. And If you can configure it to serve your purpose.

Categories

Resources