The keyword 'interface' is reserved when using lerna - create-react-app

I had a react project created using create-react-app which I am now trying to convert to a monorepo architecture. I moved all the independent code in one package, package1 and the rest of the code (along with App.tsx and index.tsx) in another, package2. Also I have added the dependency of package1 in package2.
However, when I try to do yarn start in the second package, I get this error:
Module parse failed: The keyword 'interface' is reserved (11:0)
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
What is it that I am doing wrong in the setup which is causing me this error?

It seems that it is related to tsconfig file.
so change jsx option in tsconfig.json from "preserve" to "react".

run yarn add -W craco within lerna project and
add this to your craco.config.js file within package2
const path = require('path');
const { getLoader, loaderByName } = require('#craco/craco');
const packages = [
path.join(__dirname, '../package1')
];
module.exports = {
webpack: {
configure: (webpackConfig, arg) => {
const { isFound, match } = getLoader(
webpackConfig,
loaderByName('babel-loader')
);
if (isFound) {
const include = Array.isArray(match.loader.include)
? match.loader.include
: [match.loader.include];
match.loader.include = include.concat(packages);
}
return webpackConfig;
}
}
};
and change your package.json file
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "craco eject"
}

Related

How to generate a coverage report with vscode extension tests

I'm implementing a VSCode extension. I set up the project following this link.
It generates a starter project with a src/test/runTest.ts file:
import * as path from 'path';
import { runTests } from '#vscode/test-electron';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
// The path to test runner
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './suite/index');
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.error('Failed to run tests');
process.exit(1);
}
}
main();
And a command in the package.json:
{
"compile": "tsc -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
}
Is there a way to generate a coverage report with it?
VSCode extension unittesting uses Mocha under the hood. You can generate coverage reports like in any other Typescript/Javascript project using one of the many available frameworks, e.g. c8, jest, istanbul, etc.
Install the framework of your choice, here I use c8
npm i --save-dev c8
and add to scripts
"scripts": {
"compile": "tsc -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js",
"coverage": "c8 --check-coverage npm run test"
}
Depending on your extension you might need to create a configuration file with the files you want to check for coverage. Here we are checking the compiled .js files placed under the out/ dir and we also excluding the files responsible for unittesting i.e. out/test/ (usually).
.c8rc
{
"all": true,
"include": ["out/**"],
"exclude": ["**/node_modules/**", "out/test/"],
"reporter": ["html", "text"]
}
Run the coverage script and you should get an output of your coverage
npm run coverage

Add packages to custom #frontend_components or lib folder using yarns

When migrated from bower to yarn and ran the command
yarn install
yarn created #bower_components folder and all the bower/front-end components were add inside this folder ../node_modules/#bower_components
"dependencies": {
...
"#bower_components/bootstrap": "twbs/bootstrap#^3.3.7",
"#bower_components/jquery": "jquery/jquery-dist#^3.1.1",
"#bower_components/lodash": "lodash/lodash#^4.17.12",
"#bower_components/moment": "moment/moment#^2.19.1",
... }
If, I need to create migrate from #bower_components to #frontend_components or add to public/lib folder. How do I do it?
yarn --cwd /public/lib add lodash
The way bower-away works is by creating a symlink from /bower_components to /node_modules/#bower_componets:
bower-away gets away with this by resolving all dependencies with
Bower, and adding all of them flattened to package.json
Then, your package.json file with contain bower dependencies as:
{
"dependencies": {
"#bower_components/bootstrap": "twbs/bootstrap#^3.3.7",
"#bower_components/jquery": "jquery/jquery-dist#^3.1.1",
"#bower_components/lodash": "lodash/lodash#^4.17.12",
"#bower_components/moment": "moment/moment#^2.19.1",
}
}
This will work in most scenarios. But in your case, the symlink is not working. I ran the same issue and my fix was to modify my express server and map /bower_components front-end resource into /node_modules/#bower_components backend resource with the following line:
New
app.use("/bower_components", express.static(path.join(__dirname, "/node_modules/#bower_components")));
Original
//app.use("/bower_components", express.static(path.join(__dirname, "/bower_components")));
If this is not your case, you may need to manually update front-end references to new node_modules/#bower_components folder just as advised as the original author: Adam Stankiewicz
But initially, the only change required in code is to change any
reference to bower_components with node_modules/#bower_components
(though you can link it somewhere else in postinstall script).
The workaround which I implemented to resolve this issue was by introducing a simple script and updating the package.json with a new key.
Under package.json (for all the UI related dependencies needed to work with the front-end)
...
...
"scripts": {
"postinstall": "node migrateUI.js"
},
...
"uidependencies": {
...
"bootstrap": "^3.3.7"
"jquery": "^3.1.1",
"lodash": "*",
"moment": "^2.19.1",
...
},
"dependencies": {
....
"bootstrap": "^3.3.7"
"jquery": "^3.1.1",
"lodash": "*",
"moment": "^2.19.1",
....
}
migrateUI.js
const uipackage = require('./package.json');
const packageName = Object.keys(uipackage.uidependencies);
const dir = 'public/libs';
//if the folder already exists, it ignores else creates.
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
for (let i = 0; i < packageName.length; i++) {
const element = packageName[i];
const source = path.resolve('node_modules/' + element);
const target = path.resolve('public/libs/' + element); //custom lib folder to save all UI dependencies
if (!fs.existsSync(target)) {
fs.symlinkSync(source, target, 'dir', (err) => {
if (err && err.code !== 'EEXIST') {
console.log('Error creating dependecny symlink - ', err);
} else {
console.log('Symlink for dependency created');
}
});
}
}

Different vue.config.js for npm run serve and npm run build

I'm overriding webpack config using vue.config.js:
const BundleTracker = require("webpack-bundle-tracker");
module.exports = {
publicPath: 'http://0.0.0.0:8080',
outputDir: './dist/',
chainWebpack: config => {
config.optimization
.splitChunks(false)
config
.plugin('BundleTracker')
.use(BundleTracker, [{ filename: './webpack-stats.json' }])
config.resolve.alias
.set('__STATIC__', 'static')
config.devServer
.public('http://0.0.0.0:8080')
.host('0.0.0.0')
.port(8080)
.hotOnly(true)
.watchOptions({ poll: 1000 })
.https(false)
.headers({ "Access-Control-Allow-Origin": ["*"] })
}
};
The webpack-bundle-tracker plugin generates a file called webpack-stats.json:
{
"status": "done",
"publicPath": "http://0.0.0.0:8080/",
"chunks": {
"app": [
{
"name": "app.js",
"publicPath": "http://0.0.0.0:8080/app.js",
"path": "/Users/me/dev/vue-app/dist/app.js"
}
]
}
}
My problem is that depending on whether I am in development or in production, I want the path to the file to be different.
When I run npm run serve: the generated path should be http://0.0.0.0:8080/app.js (so that the file is served by npm and I can have hot reload etc.)
When I run npm run build: the generated path should be http://0.0.0.0:8000/static/app.js (so that django can serve the file. please note the port number 8000, not 8080)
So I'm wondering if there's a way for vue.config.js to have 2 versions, one that would be used by serve the other one by build.
I know this question is like two years old.
Use the absolute path for the environment variable VUE_CLI_SERVICE_CONFIG_PATH.
You could use $PWD to instead current absolute path.
// package.json
"scripts": {
"serve": "vue-cli-service serve",
"serve:test": "env VUE_CLI_SERVICE_CONFIG_PATH=\"/var/www/html/your_project/vue.config_serve_test.js\" vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
npm run serve:test will use vue.config_serve_test.js
npm run build will use vue.config.js

Removing log statements in Create React App without ejecting

I use lots of console.log() statements while developing Apps (and I mean LOTS). How exactly can I remove them without "ejecting" from a
Create React App
What I considered but not sure how exactly to implement:
In my package.json:
"build": "react-scripts build && uglifyjs --compress drop_console build/static/js/main.xxxxx.js -o build/static/js/main.xxxxx.js
However How exactly can I know the hash suffix on the main.js file so I can call this command and save the output js file with same filename
Add this to index.js
if (process.env.NODE_ENV !== 'development') {
console.log = () => {}
}
Note that this will only suppress the messages, it will not strip them from your deployed code.
Note Nov 2020
Don't do this for library modules, it will disable console.log for the parent project.
Update Sept 2020
There is some movement on this issue on the CRA repo... go give it support/thumbs up here https://github.com/facebook/create-react-app/pull/9222
References:
How to quickly and conveniently disable all console.log statements in my code?
If you just want to suppress log output you could wrap console.log and use that instead
const log = (...msgs) => {
if (process.env.NODE_ENV === 'development') console.log(...msgs)
}
You can import / export this, but that sounds like a pain. Seems like a good thing to add to global
global.log = log
global.log('will only log in dev')
Do this in package.json scripts:
"build": "./scripts/build.sh"
and then in your project:
scripts/build.sh looks like:
#!/usr/bin/env bash
set -e;
cd "$(dirname $(dirname "$BASH_SOURCE"))" # cd to project root
react-scripts build
for f in build/static/js/*.js; do
uglifyjs --compress drop_console "$PWD/$f" -o "$PWD/$f"
done
You can try this combo of packages to override the config:
Note: from the document of react-app-rewired, this would break the the "guarantees" that CRA provides. So you should be careful before using it.
npm i -D customize-cra react-app-rewired babel-plugin-transform-remove-console
Modify your package.json, replace react-scripts to react-app-rewired except the reject. Once complete, your scripts should look like this:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
}
Then create a file under the root directory:
touch config-overrides.js
// config-overrides.js
const { override, addBabelPlugins } = require('customize-cra')
module.exports = override(
addBabelPlugins(
"transform-remove-console"
)
)
Finally, after running npm run build, all console.log gone.
I use this setup. I still need console log while in dev.
// config-overrides.js
const { override, addBabelPlugins } = require('customize-cra')
module.exports = override(
process.env.NODE_ENV !== 'development' && addBabelPlugins(
"transform-remove-console"
)
)

Running Jest tests in Vue.js

Basically, the component isn't getting compiled, so I get an Unexpected token < error when it runs into <template>
I've run the following commands:
$ npm install --save-dev jest
$ npm install --save-dev vue-jest
$ npm install --save-dev vue-test-utils
and I've out the following in package.json:
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js",
"test": "jest"
},
...
"jest": {
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/vue"
],
"moduleFileExtensions": [
"js",
"vue"
],
"scriptPreprocessor": "index.js"
}
I created a __test__ folder in the root directory with a simple test:
const Vue = require("vue");
const VueTestUtils = require("vue-test-utils");
Vue.config.debug = true;
Vue.config.async = false;
Vue.use(VueTestUtils.install);
import Hello from '../src/components/Hello.vue'
const Constructor = Vue.extend(Hello)
const vm = new Constructor().$mount()
describe('initial test', () => {
it('should be 1', () => {
expect(1).toBe(1)
})
})
I recently got this error as well, and not quite sure how to configure Vue.js so it will run using the compiler-included build:
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
Been looking around for a while, so any help would be appreciated
You need to use a Jest transform to transform Jest Vue files. A Jest transformer is a synchronous function, that takes the file and path as input and outputs transpiled code.
I maintain a npm package that does it for you - vue-jest.
npm install --save-dev vue-jest
You need to add a jest section to your package.json (or in a seperate file with --config). Your config should look something like this:
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
"^.+\\.js$": "babel-jest",
".*\\.(vue)$": "vue-jest"
}
}
This tells jest to use jest-vue as a transform for files with a .vue extension.
You can see a working repo using Vue Test Utils here - https://github.com/eddyerburgh/vue-test-utils-jest-example