I have been trying to get a working wallaby.js configuration file for my meteor project and simply can't get it to work. I've borrowed from https://github.com/xolvio/automated-testing-best-practices and I have this currently:
const babel = require('babel-core')
const path = require('path')
const wallabyWebpack = require('wallaby-webpack')
module.exports = function (wallaby) {
const webpackConfig = {
resolve: {
root: path.join(wallaby.projectCacheDir, 'imports'),
extensions: ['', '.js', '.jsx', '.json']
},
module: {
loaders: [
// JavaScript is handled by the Wallaby Babel compiler
{ test: /\.json$/, loader: 'json-loader' }
]
}
}
const wallabyPostprocessor = wallabyWebpack(webpackConfig)
const appManifest = require(path.resolve('../.meteor/local/build/programs/web.browser/program.json')).manifest;
const meteorPackageFiles = appManifest
.filter(function (file) {
return file.type === 'js' && file.path.startsWith('packages/')
})
.map(function (file) {
/* var basePath = packageStubs.indexOf(file.path) !== -1 ?
'tests/client/stubs' :
'src/.meteor/local/build/programs/web.browser';
*/
var basePath = '../.meteor/local/build/programs/web.browser'
return { pattern: path.join(basePath, file.path) }
})
return {
files: [
{ pattern: '**/*.test.*', ignore: true },
'startup/**/*.jsx',
'startup/**/*.js'
].concat(meteorPackageFiles),
tests: [
'**/*.test.*'
],
compilers: {
'**/*.js*': wallaby.compilers.babel({
babel,
presets: ['react', 'es2015', 'stage-2']
})
},
env: {
type: 'node'
},
testFramework: 'mocha'
}
}
This code successfully loads the startup files for the client-side, and the tests, but this simple test:
import should from 'should'
import buildRegExp from './buildregexp.js'
describe('buildRegExp', function() {
it('splits on word characters', function() {
buildRegExp('test this-thing:out').should.equal('(?=.*test)(?=.*this)(?=.*thing)(?=.*out).+')
})
})
fails on line 1, because the npm module "should" is not found.
Does anyone have a working wallaby config or should I just give up?
meteor test --driver-package=practicalmeteor:mocha works, so the error is in the wallaby config.
Related
I created my first vue3, ts, vuetify project, using vite (4.1.1).
vite => server is fine, no error, no warning
vite build => no error, no warning, files are generated as expected in dist and work as expected.
But but, when I run build in console, it is stuck after generation, the process never ends. And without the process ending, I cannot deploy the solution :$.
Any idea of what could prevent it from finishing ?
tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig.json",
"files": [],
"compilerOptions": {
"newLine": "lf"
},
"references": [
{ "path": "./tsconfig.config.json" },
{ "path": "./tsconfig.app.json" }
]
}
tsconfig.app.json
{
"$schema": "https://json.schemastore.org/tsconfig.json",
"extends": "#vue/tsconfig/tsconfig.web.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"#/*": ["./src/*"]
},
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"types": ["vuetify"]
}
}
tsconfig.app.json
{
"$schema": "https://json.schemastore.org/tsconfig.json",
"extends": "#vue/tsconfig/tsconfig.node.json",
"include": [
"vite.config.*"
],
"compilerOptions": {
"composite": true,
"types": ["node"]
}
}
vite.config.ts
import { defineConfig, type UserConfig } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer';
import { checker } from 'vite-plugin-checker';
import vue from '#vitejs/plugin-vue';
import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify';
import { fileURLToPath, URL } from 'node:url';
import fs from 'node:fs';
/**
* Vite Configure
*
* #see {#link https://vitejs.dev/config/}
*/
export default defineConfig(async ({ command, mode }): Promise<UserConfig> => {
const config: UserConfig = {
// https://vitejs.dev/config/shared-options.html#base
base: './',
// https://vitejs.dev/config/shared-options.html#define
define: { 'process.env': {} },
plugins: [
// Vue3
vue({
template: {
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin#image-loading
transformAssetUrls,
},
}),
// Vuetify Loader
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin#vite-plugin-vuetify
vuetify({
autoImport: true,
styles: { configFile: 'src/styles/settings.scss' },
}),
// vite-plugin-checker
// https://github.com/fi3ework/vite-plugin-checker
checker({
typescript: true,
vueTsc: true,
eslint: {
lintCommand:
'eslint . --fix --cache --cache-location ./node_modules/.vite/vite-plugin-eslint', // for example, lint .ts & .tsx
},
}),
],
// https://vitejs.dev/config/server-options.html
server: {
fs: {
// Allow serving files from one level up to the project root
allow: ['..'],
},
},
// Resolver
resolve: {
// https://vitejs.dev/config/shared-options.html#resolve-alias
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url)),
'~': fileURLToPath(new URL('./node_modules', import.meta.url)),
},
extensions: ['.js', '.json', '.jsx', '.mjs', '.ts', '.tsx', '.vue'],
},
// Build Options
// https://vitejs.dev/config/build-options.html
build: {
// Build Target
// https://vitejs.dev/config/build-options.html#build-target
target: 'esnext',
// Minify option
// https://vitejs.dev/config/build-options.html#build-minify
minify: 'esbuild',
// Rollup Options
// https://vitejs.dev/config/build-options.html#build-rollupoptions
rollupOptions: {
// #ts-ignore
output: {
manualChunks: {
// Split external library from transpiled code.
vue: ['vue', 'pinia'],
vuetify: [
'vuetify',
'vuetify/components',
'vuetify/directives'
],
materialdesignicons: ['#mdi/font/css/materialdesignicons.css'],
},
plugins: [
mode === 'analyze'
? // rollup-plugin-visualizer
// https://github.com/btd/rollup-plugin-visualizer
visualizer({
open: true,
filename: 'dist/stats.html',
})
: undefined,
],
},
},
},
esbuild: {
// Drop console when production build.
drop: command === 'serve' ? [] : ['console'],
},
};
// Write meta data.
fs.writeFileSync(
fileURLToPath(new URL('./src/Meta.ts', import.meta.url)),
`import type MetaInterface from '#/interfaces/MetaInterface';
// This file is auto-generated by the build system.
const meta: MetaInterface = {
version: '${require('./package.json').version}',
date: '${new Date().toISOString()}',
};
export default meta;
`
);
return config;
});
vite build --mode analyze : does build and opens the stat html so means the build is actually finished ? But still, it is stuck in console.
I checked circular dependencies.
Simple webpack setup, when I use import to load my scss it is completely missing from the bundle. The line where the import should be is simply missing. When I use require instead, it works.
optimization: {usedExports: true} is not the problem, I tried with and without
mini-css-extract-plugin also did not work.
when I put a typo in the scss it complains, so it is parsed but simply not bundled in the end?
index.js
require("./scss/style.scss");
//import "./scss/style.scss" <--- not working
import { createApp } from 'vue';
import App from './components/App.vue';
const el = document.getElementById('app');
createApp(App).mount(el);
webpack config
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const { DefinePlugin } = require('webpack');
const dist = path.resolve(__dirname, "dist");
module.exports = env => {
const mode = env.production == true ? "production" : "development";
const devtool = mode == "production" ? false : "inline-source-map";
return {
mode: mode,
entry: './web/index.js',
output: {
filename: 'bundle.js',
path: dist
},
optimization: {
usedExports: true,
},
devServer: {
static: {
directory: dist
},
port: 8888
},
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
}, {
test: /\.(ttf|eot|woff|woff2|svg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
},
},
}, {
test: /\.vue$/,
loader: 'vue-loader'
}]
},
plugins: [
new CleanWebpackPlugin(),
new DefinePlugin({
__VUE_OPTIONS_API__: false,
__VUE_PROD_DEVTOOLS__: false,
}),
new HtmlWebpackPlugin({
template: path.resolve("./web/index.html")
}),
new VueLoaderPlugin()
],
resolve: {
extensions: ['.js'],
alias: {
"#": path.resolve(__dirname, 'web')
}
},
devtool
};
};
I found the problem but I don't understand why webpack drops it.
Quote from https://webpack.js.org/guides/tree-shaking/
Note that any imported file is subject to tree shaking. This means if you use something like css-loader in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode:
In my package.json I put
"sideEffects": false,
to be able to use treeshaking.
But I had to disable it in the loader rule
{
test: /\.(sa|sc|c)ss$/,
use: ['style-loader','css-loader','sass-loader'],
sideEffects: true <----
}
I want to use Linaria library(https://github.com/callstack/linaria) with nextJS.
Now, I implemented according to the document. But occurred the next error.
Global CSS cannot be imported from files other than your Custom . Please move all global CSS imports to pages/_app.js.
Read more: https://err.sh/next.js/css-global
I understood this error. But I wondered. How can I use Linaria with NextJS?
.babelrc
{
"presets": ["next/babel", "linaria/babel"],
}
next.config.js
const path = require("path");
module.exports = {
webpackDevMiddleware: (config) => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
};
return config;
},
webpack: (config) => {
config.module.rules.push({
test: /\.tsx$/,
use: [
{
loader: "linaria/loader",
options: {
sourceMap: process.env.NODE_ENV !== "production",
},
},
],
});
return config;
},
};
There is a recent linaria issue on this topic. It seems people are finding success with the following next.config.js config:
const withCSS = require('#zeit/next-css');
module.exports = withCSS({
webpack(config) {
// retrieve the rule without knowing its order
const jsLoaderRule = config.module.rules.find(
(rule) => rule.test instanceof RegExp && rule.test.test('.js')
);
const linariaLoader = {
loader: 'linaria/loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
};
if (Array.isArray(jsLoaderRule.use)) {
jsLoaderRule.use.push(linariaLoader);
} else {
jsLoaderRule.use = [jsLoaderRule.use, linariaLoader];
}
return config;
},
});
I've added .scss styling to my site. The .scss files sit next to their .jsx components.
I reference the styles in .jsx like this:
import styles from './guest-card.component.scss'
...
<Card className={styles.card}>
Everything looks great when I run my local server webpack-dev-server --inline --progress --config build/webpack.cold.conf.js
When I build for distributing the app, such as Development machine or QA machine I run npm run build. This builds a dist folder with everything compiled.
When I view my site on a dev/qa server my styles are missing.
Looking in the dist folder I see a /static/css/app.css with my compiled styles. Great! The styles look correct.
My question: What do I do to include these /static/css/app.css in my production site? I tried adding a <link rel="stylesheet" ... to include it and im sure that would work but would give a 404 on my local machine.
Whats the correct way of having styles built
So my question is:
My question is - how do I get my app to reference this new app.css? If I add a
build.js
'use strict';
require('./check-versions')();
process.env.NODE_ENV = 'production';
const ora = require('ora');
const rm = require('rimraf');
const path = require('path');
const chalk = require('chalk');
const webpack = require('webpack');
const config = require('../config');
const webpackConfig = require('./webpack.prod.conf');
const spinner = ora('building...');
spinner.start();
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err;
webpack(webpackConfig, function (err, stats) {
spinner.stop();
if (err) throw err;
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n');
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'));
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'));
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
});
webpack.prod.conf.js
const paths = require('./paths');
const utils = require('./utils');
const webpack = require('webpack');
const config = require('../config');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
const env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: require('../config/prod.env');
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].js'),
chunkFilename: utils.assetsPath('js/[id].js')
},
resolve: {
alias: {
settings: `${paths.settings}/dist.js`
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': env
}),
// UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].css'),
// set the following option to `true` if you want to extract CSS from
// codesplit chunks into this main css file as well.
// This will result in *all* of your app's CSS being loaded upfront.
allChunks: false,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
host: '#_host_#',
template: 'index.html',
inject: false,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vender modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(paths.nodeModules) === 0
);
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: paths.static,
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
]),
// copy any extra assets to root dist
new CopyWebpackPlugin([
{
from: `${paths.root}\\web.config`,
to: config.build.dist,
ignore: ['.*']
}
])
]
});
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin');
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
`\\.(${
config.build.productionGzipExtensions.join('|')
})$`
),
threshold: 10240,
minRatio: 0.8
})
);
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = webpackConfig;
webpack.base.conf.js
const paths = require('./paths');
const utils = require('./utils');
const config = require('../config');
module.exports = {
context: paths.root,
entry: {
app: './src/main.jsx'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'#': paths.src,
api: paths.api,
settings: `${paths.settings}/local.js`
}
},
externals: {
bamboraCheckout: 'customcheckout'
},
module: {
rules: [
...(config.dev.useEslint ? [{
test: /\.js$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [paths.src, paths.test],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
}] : []),
{
test: /\.(js|jsx|mjs)$/,
loader: 'babel-loader',
include: [paths.src, paths.test]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
};
webpack.cold.conf.js
const paths = require('./paths');
const merge = require('webpack-merge');
const devWebpackConfig = require('./webpack.hot.conf.js');
module.exports = new Promise(resolve => {
devWebpackConfig.then(base => {
let webpackConfig = merge(base, {
resolve: {
alias: {
api: `${paths.api}/fakes`
}
}
});
resolve(webpackConfig);
})
});
If you miss link to your generated style file in index.html then you should search for problem here, because this plugin is responsible for it
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
host: '#_host_#',
template: 'index.html',
inject: false,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
}
I just looked through plugin documentation, probably you need to remove inject: false. Default is true, and is putting your assets into index.html
I am currently using css module with miniCssExtractPlugin, it is wired it is not working,it do extract css into a separate css file, but the css file is empty.when i use style-loader it looks good with css module, but it will not extract css to a separate file.
const cssDevRules=[
{
loader:'style-loader'
},
{
loader:'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:5]',
},
{
loader:'sass-loader',
}];
but when i try to use miniCssExtractPlugin in production mode, the generate css file is empty.code as below:
const cssProdRules=[
{
loader: MiniCssExtractPlugin.loader,
},
{
loader:'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:5]',
},
{
loader:'sass-loader',
}];
i also try to use style-loader with ExtractTextPlugin, still not working, anyone can tell me how to fix this up?
i will put all my webpack.config.json here for your reference.
const path = require('path');
const glob = require("glob");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const PurifyCSSPlugin = require("purifycss-webpack");
const isProd = process.env.NODE_ENV === 'production';
const PATHS = {
app: path.join(__dirname, "src"),
};
const MiniCssPlugin = new MiniCssExtractPlugin({
filename: "[name].css",
});
const PurifyCssPlugin = new PurifyCSSPlugin({
paths: glob.sync(`${PATHS.app}/**/*.js`, { nodir: true }),
});
const cssDevRules=[
{
loader:'style-loader'
},
{
loader:'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:5]',
},
{
loader:'sass-loader',
}
];
const cssProdRules=[
{
loader: MiniCssExtractPlugin.loader,
// loader:'style-loader'
},
{
loader:'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:5]',
},
{
loader:'sass-loader',
}
];
console.log("is prod:"+isProd);
const baseConfig = {
module: {
rules: [
{
test: /\.(css|sass|scss)$/,
use: isProd? cssProdRules:cssDevRules,
exclude: /node_modules/,
},
]
},
};
if(isProd){
baseConfig.plugins=[
MiniCssPlugin,
PurifyCssPlugin,
];
}
module.exports = baseConfig;
the production mode is not working , the css generate by MiniCssExtract is empty, anyone can help on this?