What module can strip debugs in webpack solutions? - reactjs

I am running a reactjs app with gulp/webpack and tried this:
https://github.com/yahoo/strip-loader.
However it does not work( throws errors in my reactjs code). How to get it working or what is another solution?
EDIT
I added this to the loaders section of the webpack.config:
new webpack.optimize.UglifyJsPlugin({
drop_debug: true
})
I have installed the plugin with npm but it does not filter the debugger statements from my reactjs code?

You can use UglifyJsPlugin() and pass the drop_debugger: true property.
To utilize this property you need to pass it to the compress property inside of the options argument.
new webpack.optimize.UglifyJsPlugin(
compressor: {
drop_debugger: true
}
);
This is an UglifyJS specific property and webpack can pass those directly through compress. Ironically looking at the source of the plugin it can also take the property compressor as an alt property.

you can use strip-loader plugin in webpack.
var WebpackStripLoader = require('strip-loader');
WebpackStripLoader.loader('console.log', 'console.error', 'debugger')

Related

Recoil Duplicate atom key when using with Webpack Module Federation

I'm using Webpack Module Federation to create 2 React applications: host and child.
In the host, I create atoms.ts and selector.ts filed and I expose them via the plugin under the expose section:
exposes: {
"./atoms": "./src/recoil/atoms.ts",
"./selectors": "./src/recoil/selectors.ts",
}
Inside the child, I just consume that via the remotes section:
remotes: {
host: "host#http://localhost:3000/remoteEntry.js",
}
Then, in the code of the child I use that like that:
import {someSelector} from "host/selectors"
const val = useRecoilValue(someSelector);
It's working fine but I got this warning in the console:
Duplicate atom key "userAuthState". This is a FATAL ERROR in
production. But it is safe to ignore this warning if it occurred because of
hot module replacement.
Does anyone face that issue and know if it's really a problem or how we could hide the warning?
Another related q:
Is it ok that the host will contain <RecoilRoot> and also the child will contain <RecoilRoot> ? because I want both will manage their own state but also share atom/selectors.
Thanks!
Regarding your second question:
Yes, this is totally fine. The nested <RecoilRoot> will create its own context and every atom referenced below the second root will be independent from the upper root. This is also explained in the docs.
Regarding the first question: As the log states this is fine as long as it occurs during development. Sometimes during the hot module replacement recoil throws away atoms and reinstantiates them causing this duplication to happen internally.
But as long as this warning doesn't pop up in your production code, everything is fine.
Are you importing the atoms or the selectors in your host application using a local path?
You need to include in your host webpack config its own entrypoint as remote and import your atoms from 'host/atoms'
I think this could solve your issue.
You can ignore the warning output (if you can bare it), functionality is not affected.
Also, you can install the intercept-stdout package and add the following to next.config.js (outside of the exported configuration):
const intercept = require("intercept-stdout")
// safely ignore recoil warning messages in dev (triggered by HMR)
function interceptStdout(text) {
if (text.includes("Duplicate atom key")) {
return "";
}
return text;
}
if (process.env.NODE_ENV === "development") {
intercept(interceptStdout);
}
This way can omit the annoying warning in console.

AudioWorklet error: DOMException: The user aborted a request

I've successfully instantiated a simple AudioWorklet in React and wish to start a simple oscillator like in Google's example. In order to test run it, I am rendering a button whose onClick event calls the following:
src/App.jsx:
userGesture(){
//create a new AudioContext
this.context = new AudioContext();
//Add our Processor module to the AudioWorklet
this.context.audioWorklet.addModule('worklet/processor.js').then(() => {
//Create an oscillator and run it through the processor
let oscillator = new OscillatorNode(this.context);
let bypasser = new MyWorkletNode(this.context, 'my-worklet-processor');
//Connect to the context's destination and start
oscillator.connect(bypasser).connect(this.context.destination);
oscillator.start();
})
.catch((e => console.log(e)))
}
The problem is, on every click, addModule method is returning the following error:
DOMException: The user aborted a request.
I am running Chrome v66 on Ubuntu v16.0.4.
src/worklet/worklet-node.js:
export default class MyWorkletNode extends window.AudioWorkletNode {
constructor(context) {
super(context, 'my-worklet-processor');
}
}
src/worklet/processor.js
class MyWorkletProcessor extends AudioWorkletProcessor {
constructor() {
super();
}
process(inputs, outputs) {
let input = inputs[0];
let output = outputs[0];
for (let channel = 0; channel < output.length; ++channel) {
output[channel].set(input[channel]);
}
return true;
}
}
registerProcessor('my-worklet-processor', MyWorkletProcessor);
My code is straight JavaScript, not React, but I got the same error because the path provided to addModule was incorrect. In my case, both the script that calls addModule and the script provided as the argument to addModule reside in the same directory ("js"). In spite of that, I still had to include this directory in the path to eliminate the error:
...addModule('js/StreamTransmitter.js')...
I hope this helps. Good luck!
For anyone else getting this mysterious error, swallow your pride and check the following:
The processor doesn't have any errors.
The processor is calling external modules with proper path to the external file(s).
The external modules don't have any errors.
The promise will abort when external modules that are loaded via "import" have errors, or the paths to the modules can't be resolved (e.g. the path's to the modules are wrong and don't point to existing files).
This worked for me: serve your worklet files from public folder instead of src. The addModule(url) function points there by default, so addModule('worklets/foo.js') references file public\worklets\foo.js
Source: https://hackernoon.com/implementing-audioworklets-with-react-8a80a470474
This seems to be a bug in the Chromium module loader, it parses the worklet/processor.js file by removing whitespace, which in turn causes it to have JavaScript syntax errors everywhere, which then finally causes this generic non-explanatory error message to show up.
The solution is to serve your worklet-processors (e.g. worklet/processor.js in your case) with:
Content-Type: application/javascript
or
Content-Type: text/javascript
I also experienced this error but due to a Webpack issue.
Turns out webpack doesn't support worklets like it supports web workers (see this issue).
I would recommend using worker-url with webpack.
Install worker-url
npm i --save-dev worker-url
Update your webpack config to include the WorkerUrl plugin.
const WorkerUrlPlugin = require('worker-url/plugin');
module.exports = {
// ...
plugins: [new WorkerUrlPlugin()],
// ...
};
Use WorkerUrl like so:
import { WorkerUrl } from 'worker-url';
const workletUrl = new WorkerUrl(
new URL('./random-noise-processor', import.meta.url),
{ name: 'worklet' },
);
await context.audioWorklet.addModule(workletUrl);
The Error "DOMException: The user aborted a request." happens when the AudioWorklet.addModule() function cannot load the file from the path or URL you provided. Refer to this MDN page
The api AudioWorklet.addModule() expects a String containing the URL of a JavaScript file with the module to add.
It can be an internal URL that points to your public folder where the browser loads your static files in this case -> 'worklet/processor.js if the worklet folder is inside the public directory of your React app.
You can modify your code as below.
this.context.audioWorklet.addModule('worklet/processor.js')
In this case the audioWorklet.addModule() method expects the path to point to your public folder. It can also be an external URL for example a link to Github repository that loads the JS file.
Changing:
this.context.audioWorklet.addModule('worklet/processor.js')
with
this.context.audioWorklet.addModule('../worklet/processor.js')
worked for me.

Setting global variables in webpack for front-end config?

I have a different URL for our api depending if it's development or production for a react app.
Using webpack, how can I set an env var like __API_URL__ and then change that depending if it's built using webpack.config.dev vs webpack.config.prod
I thought the answer may be in webpack.DefinePlugin but no luck.
new webpack.DefinePlugin({
__API_URL__: 'localhost:3005',
}),
I'd expect __API_URL__ to be available as a global but no such luck.
What would be the right way to do this? Also key thing is that no express server on the prod deploy. So this has to happen during the build...
As Michael Rasoahaingo said, the DefinePlugin works similar like replacing values with regular expressions: It replaces the value literally in your source code. I would not recommend to use the DefinePlugin for this kind of task.
If you want to switch configs based on the environment, you could use resolve.alias for that. Just import your config like this:
var config = require("config");
and then add a mapping in your webpack.config.js:
resolve: {
alias: {
config$: require.resolve("path/to/real/config/file")
}
}
DefinePlugin is not working as you expected. It doesn't expose __API_URL__ as a global variable.
According to the documentation: "The values will be inlined into the code which allows a minification pass to remove the redundant conditional."
So, it will find all occurence of __API_URL__ and changes it.
var apiUrl = __API_URL__
and
__API_URL__: '"localhost:3005"' // note the ' and "
become
var apiUrl = "localhost:3005"

Set a store with a function in app.js doesn't work in production build?

I'm trying to create a search form view based on the following example of Sencha :
http://try.sencha.com/touch/2.0.0/examples/list-search/viewer.html
I made a few changes just not to create the view by code but export it in a view.
To set up the store, i use this in the config :
store: Preconisations.app.getStoreAdherents(),
where Preconisations is my project name and getStoreAdherents the function set in the app.js:
getStoreAdherents: function () {
if (!this.storeAdherents) {
var gestionAdherent = new DAL_Adherent(); // custom classes
var tc = gestionAdherent.GetAll(); // and functions which returns a json string with data
this.storeAdherents = Ext.create('Ext.data.Store', {
model: "Preconisations.model.ADHERENT",
data: tc,
sorters: 'nom',
groupField: 'code'
});
}
return this.storeAdherents;
}
Now, everything works fine but when i make the testing or the production build, i've got this error :
Uncaught TypeError: Cannot call method 'getStoreAdherents' of undefined
at the store definition...
Maybe, there's a better way to set up the store by code but i can't understand why it's working in developpement and not with the production or testing build...
Is anyone had this problem ? Or how do you set up dynamically a store with a function ?
Thanks... I'm banging my head on the wall on this one...
It is clear that you have a build dependency issue in Ext Build. In the code snippet posted, there is a chance that you missed to add "Preconisations.model.ADHERENT" to a class path. If so, please add the following to your app.js
requires: ["Preconisations.model.ADHERENT"]
If the issue persist, Please do the following diagnostics :
Run your app (development mode) in Google Chrome with the Console open; Look for warnings that states a particular class is being synchronously loaded and add requires statement for those classes.
In fact i think there's a bug in setting a store dynamically in the config.
I found this workaround which work in developpement and in build production :
I don't specify a store : xxxx in the view.
Instead, in a controller i put this code in the launch function :
this.getMainView().setStore(this.getStoreAdherents());
where getMainView is a reference to my view.
That's all !

Removing _dc parameter in Ext

Using Ext, default Ext.Ajax add to GET-request _dc parameter. For example
GET /ConnViewProcessing/?_dc=1263286227619
How to remove this parameter?
PS: it's necessary to manually cache response to ETag and If-None-Match.
Set disableCaching option to false:
Ext.Ajax.disableCaching = false;
Using Ext JS 4.1, and after adding the following code to app.js, the _dc parameter disappears:
// Disable _dc parameter
Ext.Loader.setConfig({
disableCaching: false
});
// My App
Ext.application({
The proper way to accomplish that with Sencha Cmd 6.x is to set a (global) switch in app.json (because all of those hacks and overrides might interfere unnecessarily with the functionality):
"loader": {
"cache": true
},
Then run sencha app refresh, in order to update the application's bootstrap.json.
Alternatively, one can configure Ext.Loader (at run-time):
Ext.Loader.setConfig({disableCaching: false});
When scrolling upwards and reading the actual question, concerning Ext.Ajax (per request):
Ext.Ajax.request({url: '/ConnViewProcessing', disableCaching: false});
The result: no more _dc parameters on scripted requests.
#see Sencha Cmd 6.x - The Microloader.
Note that the use of Ext.Loader has changed in ExtJS 5.
In ExtJS 5, caching can be disabled:
temporarily by adding "?cache" to the end of the URL
by setting a cookie called 'ext-cache' with the value of 1
or by editing the file .sencha/app/Boot.js and setting the '_config.disableCaching' property to be true (overwriting the dynamic lookup).
I am using ExtJS 4.2, but this should work for Ext JS 4.1 and on. In the proxy there is a property called noCache you should set this to false.
Ext4.define('Server',{
extend: 'Ext4.data.Model',
fields: [
{name: 'id'},
{name: 'key'},
{name: 'value'}
],
proxy: {
type: 'rest',
url : 'yaddayaddayadda',
noCache: false,
reader : {
type: 'json'
}
}
});
The reason my code says Ext4. is because I am using the sandbox mode as I move old Ext JS 3x code into 4.2
This should work with extjs 4.0.7:
Ext.Loader.config.disableCaching = false;
Setting the flag disableCaching to false (double negation - yay!) on the Ext.data.Connection should do the trick.
For more, look at the disableCaching-documentation.
(Please note that quite a few classes in Ext seem to have the option available, so you might have to muck around a bit.)
For those that want to set "disableCaching: false" in Sencha Architect 3+, here is how..:
In the project inspector window, select the top node,
"Application"
Then in the "Config" window below that where you
set the object properties, etc, select "Loader Config".. in my case
I had to click the "+" to the right of this as I hadn't set any
items yet. This will create a new "LoaderXX" object in the "Project
Inspector" window above; Loader25 in my case.
Now either select the new object in the
"Project Inspector" window, or click on the right arrow beside the
new "LoaderXX" (Loader25 in my case). This will take you to the
properties for the object.
Untick the "disableCaching" item.
Save the project and refresh the browser window, and enjoy persistent breakpoints, etc, etc in Chrome.
The only way I was able to disable _dc in ExtJS 4.2.x globally on my project:
Ext.define('Ext.data.Connection', {override:'Ext.data.Connection', disableCaching:false });
Ext.define('Ext.data.proxy.Server', {override:'Ext.data.proxy.Server', noCache:false });
Ext.define('Ext.data.JsonP', {override:'Ext.data.JsonP', disableCaching:false });
This is ugly, but any other ideas?
This is how I did this:
Ext.Ajax.request({
url: url,
disableCaching:false
});
I decided that I wanted the cache to be destroyed client side, but server side I was using my own caching mechanism (PHP's APC).
I left the _dc in the Ext ajax request, but then removed it from the REQUEST_URI, and then use the REQUEST_URI as the basis for the cache key
I found this useful: Regular expression to remove one parameter from query string
If you develop under Sencha CMD you can do like this
http://localhost:1841/?disableCacheBuster
or just
http://localhost:1841/?cache
For all who are looking for a way to disable it in a newer version:
proxy: {
type: 'ajax',
noCace: false
}
I use Ext.NET on top of Ext.JS. It adds some more voodoo to Ext.js...
I tried to get rid of the dc= parameter, but all mentioned configurations did not work. So, this is my uber-effective, uber-dirty solution:
Ext.Date.now = function () { return ""; }
As far as I can see, Ext.Date.now() is only used for the caching logic. So it should be relativity save.

Resources