The Problem
Trying to lint an old React application that has 30+ console.logs() throughout the code base. I setup a linter and code formatter, ESLint and Prettier respectively.
This setup works great and it shows me where the console.logs() are in the source. But, the --fix flag for ESLint does not remove the logs. Is there any way to automatically remove console.logs()? I've seen articles on how to do this via webpack to prevent the logs from going into production, however, I would like to remove these earlier in a pre-commit or pre-push hook for instance.
What I've Tried
I tried setting up a script using gulp-strip-debug. It fails with an assertion error. When I changed the src path from './src/**.js' to './**.js' I do not get the assertion error but nothing happens.
Learned about this from Jun711 blog. The "How to remove console log from your JavaScript files programmatically?" blog post.
Gulpfile
gulpfile.js: root of project directory
const gulp = require('gulp');
const stripDebug = require('gulp-strip-debug');
gulp.task(
'strip-debug',
() =>
gulp
.src('./src/**.js') // input file path
.pipe(stripDebug()) // execute gulp-strip-debug
.pipe(gulp.dest('./')) // output file path
);
Package.json
{
"name": "end-the-pandemic",
"version": "1.0.0",
"dependencies": {
"shelter-in-place": "11.5.20",
"stay-home": "11.5.21",
"who-is-still-voting-for-trump": "11.3.20",
"seriously-why": "2.0.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"lint": "eslint '*/**/*.js' --quiet --fix",
"clean": "gulp strip-debug",
"test": "react-scripts test",
"eject": "react-scripts eject",
},
...
Terminal
yarn clean
Output
AssertionError [ERR_ASSERTION]: Task function must be specified
Obviously, I could have done a search and deleted most of them manually with the time I spent writing this question but for future reference, is there anyway to do this with a command? I would like to put yarn clean in a pre-commit hook if possible.
You could make this trick it would be good in this case
if (env === 'production') {
console.log = function () {};
}
this will overwrite the real log function into an empty one
make sure you add it at the top of your react app
Another solution
there is a package called babel-plugin-transform-remove-console could help you
after installing it from npm
npm install babel-plugin-transform-remove-console
after installing create a .babelrc file in your project root dir
and add this line to it
{
"plugins": ["transform-remove-console"]
}
Related
I would like to run a JavaScript file in my Angular application every time I run ng build. To be more precise, I want this file to be executed before the build process so that the changes that it makes are present in the build.
Its a simple script that reads the app version and its dependencies and write them to an object.
The file is called pre-build.js and I have tried configuring the build command in package.json as follows, however I can see that the script was not executed:
{
...
...,
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "node pre-build.js && ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
...,
...,
}
The path of the script is ./pre-build.js.
I assume that I have to change more configurations in order to achieve this but I am not able to find out where. Any leads will be appreciated.
Edit:
This is the content of pre-build.js:
const path = require('path');
const fs = require('fs');
const appVersion = require('./package.json').version;
const appDeps = JSON.stringify(require('./package.json').dependencies);
const versionFilePath = path.join(__dirname + '/src/environments/version.ts');
const src = `export const version = '${appVersion}';\nexport const buildTime = '${new Date()}';\nexport const deps = ${appDeps};`;
// ensure version module pulls value from package.json
fs.writeFile(versionFilePath, src, (err) => {
if (err) {
console.log(err);
}
});
When I run node pre-build.js in the terminal, the code works fine and updates the version.ts file. But i want to somehow automatically execute this command every time i run ng build. Which so far i was not able to do so.
Edit
The correct answer to this problem is that you shouldn't run ng build but should run npm run build since you want to execute the script. When you do ng build this would only trigger the build for angular and wouldn't update your version file indeed.
Below is an example of your exact same code when doing npm run build, so make sure to update how you build.
Give it a try and let me know if this is still an issue.
Old answer
You can create a ".sh" script to other execute everything you need. This might be helpful later on to add more pre or post build commands
Here is an example
package.json
"scripts": {
"build:angular": "ng build",
"build": ./build.sh
}
build.sh
#!/bin/bash
node ./pre-build.js
npm run build:angular
Make sure that pre-build is executable so is the build.sh (chmod https://askubuntu.com/questions/229589/how-to-make-a-file-e-g-a-sh-script-executable-so-it-can-be-run-from-a-termi )
Try like this:
node ./pre-build.js && ng build
I'm starting a CDK lambda project which gets the source code like this:
code: lambda.Code.fromAsset("resources"),
handler: "synthetic_test.main",
There's a single javascript file synthetic_test.js in that folder.
This seems to work but I can't figure out how to make it so that I could do:
const axios = require("axios");
in that file.
For some reason it seems to be able to import:
const AWS = require("aws-sdk");
but nothing else.
I did yarn add axios which added it to the package.json of my CDK project. But that does not really seem to help the lambda a lot.
The AWS Lambda runtime environment includes native language libraries and the relevant language-specific AWS SDK.
It does not contain arbitrary third-party packages. You need to either package those dependencies with your code or create a Lambda Layer that includes the dependencies and configure your Lambda function to use the Lambda Layer.
To package CDK app dependencies, see #aws-cdk/aws-lambda-nodejs and here.
I went with packaging dependencies with my code
My cdk went to
// 👇 define PUT account function
const putAccountLambda = new lambda.Function(this, "put-account-lambda", {
runtime: lambda.Runtime.NODEJS_14_X,
handler: "main.handler",
code: lambda.Code.fromAsset(path.join(__dirname, "/../src/put-account/dist")),
environment: {
REGION,
ADMINS_TABLE,
ADMINS_TABLE_PARTITION_KEY,
HASH_ALG,
}
})
With dist being the folder with a packed main.js file. And this file has a handler entrypoint. I had to update the package.json of these lambdas with packed dependencies.
{
"name": "put-account",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --mode=production --env env=prod",
"build:dev": "webpack --mode=development --env env=dev"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.66.0",
"webpack-cli": "^4.9.1",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"aws-sdk": "^2.1058.0",
"crypto": "^1.0.1",
"uuid": "^8.3.2"
}
}
And I updated the package.json of my cdk project to these scripts.
"build": "tsc && npm run build:webpack",
"build:webpack": "for file in ./src/*; do (cd $file && npm i && npm run build) & done",
"build:beta": "tsc && npm run build:webpack:beta",
"build:webpack:beta": "for file in ./src/*; do (cd $file && npm i && npm run build:dev) & done",
Notice that my file structure is as follows:
./
bin
lib
src
package.json
With src holding the source code for my project's lambdas.
I am not sure if you are familiar with webpack, but I have divided my webpack configuration in common, dev, prod.
A dev webpack configuration is specially useful for debugging because otherwise you lose line numbers among other useful information when something goes wrong on runtime.
I am reading the data from an API and downloading a file. I want to save the same file in public folder of react application.
this.state = {
fileDownloadUrl: null,
fileName: '',
};
below is the method.
downLoadFile(e) {
e.preventDefault();
axios
.get(
'http://localhost:8080/file_download/en'
)
.then((res) => {
var output = res.data;
const blob = new Blob([output]);
const fileDownloadUrl = URL.createObjectURL(blob);
this.setState({ fileDownloadUrl: fileDownloadUrl }, () => {
this.dofileDownload.click();
URL.revokeObjectURL(fileDownloadUrl);
this.setState({ fileDownloadUrl: '' });
});
});
}
code for downloading the file.
<a
className="hidden"
download={this.state.fileName + '.json'}
href={this.state.fileDownloadUrl}
ref={(e) => (this.dofileDownload = e)}
>
download it
</a>
Is there anyway I can modify the code so that file can be saved in the public folder of react application. later this file will be used for translation.
There's no way to automatically download a file and save it in a specific location on your hard disk from a frontend app running inside a browser. The users of your app will decide how the file is saved based on their browser settings.
If you're trying to achieve that kind of thing, then that's wrong and you should consider another approach.
It's not possible because this poses a security risk.
Most of the OS will defaults the download to download folder.
Pure browser-JavaScript is not be able to get information about the user's filesystem. The default download path might also contain sensible information, which is risky.
To sum up the question, the challenge is to fetch or otherwise produce certain static file assets for React to consume.
As other answers pointed out, it's impossible to do from React itself. I'd add, if it were possible, that would be inefficient, unsafe and insecure.
Architecturally, it's best to create a file-generating script and run it before the React application's build step.
I'm using such setup myself. For example, if you checked my package.json I've got scripts:
{
"scripts": {
"--------- BUILD ---------": "",
"build": "npm run ops && run-s build:*",
"build:remix": "remix build",
"build:css": "npm run generate:css",
"--------- DEV ---------": "",
"dev": "npm run ops && run-p dev:*",
"dev:remix": "cross-env NODE_ENV=development remix dev",
"dev:css": "npm run generate:css -- --watch",
"generate:css": "sass styles:app/styles app/components",
"format": "prettier --write .",
"--------- TEST ---------": "",
"start:mocks": "cross-env NODE_ENV=production node --require ./mocks --require dotenv/config ./build/server.js",
"test": "vitest run --coverage",
"test:e2e:dev": "start-server-and-test dev http://localhost:3000 \"cypress open\"",
"pretest:e2e:run": "npm run build",
"test:e2e:run": "cross-env PORT=8811 start-server-and-test start:mocks http://localhost:8811 \"cypress run\"",
"--------- LINT ---------": "",
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
"typecheck": "tsc -b && tsc -b cypress",
"validate": "run-p \"test -- --run\" lint typecheck test:e2e:run",
"--------- OPS ---------": "",
"ops": "run-p ops:*",
"ops:static": "node ./ops/extract-static-data.mjs",
"ops:search": "node ./ops/extract-search.mjs",
"ops:rss": "node ./ops/extract-rss.mjs"
}
}
notice how ops group of scripts is triggered before the React build step. I generate static fresh files:
lump of all h2 heading strings for aside to set currently active anchor
all MDX front matter lump of all articles for rendering MDX outside normal routes (article lists, search etc.)
the final HTML of RSS feed; I render HTML with all remark goodies such as syntax titles, syntax highlighting and typography
compile the search data file and index file (for warm starts) for fuse.js
I'd fetch locales this way too: npm-triggered script would fetch and atomically save a file straight into /public/.
It's done during build-time rather than runtime to simplify the setup and lower the server bill. I disagree with Mr. Dodds in this aspect; more so, runtime libraries such as mdx-bundler don't even support pure ESM, so actually, runtime-oriented approaches often don't even work. For example, if you take the same Mr. Dodds' blog, it doesn't have the current anchor tracking in single posts or site-wide search or automated typography processing.
PS. Interestingly, if you look at the static site generators, 11ty lets you fetch extra sources from the 11ty config itself, that's where you would fetch the locales of yours on 11ty.
We have front-end engineers around the world, so when we run Date.prototype.toLocaleString, we get different results. Sometimes, these differences show up in Jest tests. If someone in a different country runs a Jest test, it may fail because of toLocaleString. What are some ways to force Jest to use a certain locale?
As a bandaid solution, I added the following to the failing tests:
const toLocaleString = Date.prototype.toLocaleString;
// eslint-disable-next-line no-extend-native
Date.prototype.toLocaleString = function(locale = 'en-US', ...args) {
return toLocaleString.call(this, locale, ...args);
};
You should add full-icu to your dev dependencies:
npm i full-icu --save-dev
And run your tests like this:
NODE_ICU_DATA=node_modules/full-icu jest
So if you're running a npm script you package.json will look like this:
"scripts": {
"dev": "...",
"test": "NODE_ICU_DATA=node_modules/full-icu jest",
},
In case of using React Scripts:
"scripts": {
"dev": "...",
"test": "NODE_ICU_DATA=node_modules/full-icu react-scripts test",
},
And if you are using Jest VSCode extension you'll have to change this configuration:
`"jest.pathToJest": "npm run test --"`
my main problem which I am trying to solve is to generate JSON files from React source code.
currently I am using for translations react-intl universal package which is working in my App https://github.com/alibaba/react-intl-universal
To solve my main problem I have found this package (I have found only this one, so, if you recommend me something else, i will be glad)
https://github.com/GertjanReynaert/react-intl-translations-manager
As is in guide i have created translationRunner.js (which is in src folder)
const manageTranslations = require('react-intl-translations-manager').default;
manageTranslations({
messagesDirectory: 'src/translations/extractedMessages',
translationsDirectory: 'src/translations/locales/',
languages: ['nl'] // any language you need
});
in my package.json added
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"manage:translations": "node ./translationRunner.js"
in render method i have something like
<h1>{intl.get('APPBARTITLE')}</h1>
if i run translationRunner.js I obtain nl.json which looks like
{
}
How to obtains json file with my message?
Apparently you need to run
npm run build
first. The translation manager does not extract the keys you want translated, the babel plugin does.
https://github.com/GertjanReynaert/react-intl-translations-manager/issues/49