How to ignore multiple directories and files using electron releoad - javascript

I have an Electron project using electron-reload, the file structure is:
./public/templates/ --------- contains some html that should be watched and trigger reload
./public/templates/test/ ---- contains some test/experimental html that should be ignored/not trigger reload
./notes --------------------- just containing some notes, this should not trigger reload
./node_modules -------------- should be ignored
./main.js ------------------- should trigger reload on change
I know I can ignore directories by setting the option ignored on requiring electron reload in main.js.
This uses chokidar for filtering, ignored option is described here
But I don't get how to ignore multiple paths.
I tried to require electron reload like this:
require('electron-reload')(__dirname, {ignored: /node_modules|notes|public\/templates\/test/gi});
But when I change a file in
public/templates/test/ the application is reloading.
electron 5.0.6
electron-reload 1.5.0
Thanks in advance
Kevin

You can check the eletron-reload module.
electron_reload(paths, options):
paths: a file, directory or glob pattern to watch
options will default to {ignored: /node_modules|[\/\\]\./, argv: []}.
Then in the ignored field you put Regular Expressions of what you want to ignore. You can check the regular expressions here
For example, if I want to ignore all the folders: node_modules, files/img, resorces within my directory. The main.js would be:
//main.js
const ignoredNode = /node_modules|[/\\]\./;
const ignored1 = /resources|[/\\]\./; // all folder resorces => resources
const ignored2 = /files\/img|[/\\]\./; //all folder files/img => files/img
if (process.env.NODE_ENV !== 'production'){
require('electron-reload')(__dirname, {ignored: [ignored1, ignored2, ignoredNode] });
}
This prevents an application reload whenever there are changes within the folders: node_modules, files/img, resorces.
Now you have to use regular expressions for your purpose.

Related

Hot-reload doesn't inject change on file change

I have the following problem and have spent a lot of time trying to solve it without success. I have a folder that contains all the labels of my website in X languages. The problem is that when I make a change in that folder it is not updated in the browser, like you have when you change your layouts or content. What is strange is that when I update one file in that folder, I can see in the terminal that a change was made in the file, but when I check the dist/*.html file, I cannot see the new label in the dist/**.html it is not injected. I think it is a problem with browser-sync.
I tried playing with addWatchTarget() and setBrowserSyncConfig({ files: [...] }) in .eleventy.js config file, but without success, the changes are still not injected.
Also, I found a working case. I update my translations file, then just save in .elevently.js to trigger the watch thingy. It will inject the new labels in the dist/**.html.
Project with the issue
Here is my structure
i18n
-- index.js // custom script to pick the good label in the translations folder
src
-- _assets
-- _includes
-- content
-- translations
---- index.js
---- en
---- jp
.eleventy.js
...
.eleventy.js
const i18n = require('./i18n');
const translations = require('./src/translations');
module.exports = (config) => {
// Custom i18n filter
config.addFilter('i18n', (key, page, data) => {
const pluginOptions = {
translations,
languages: LANGUAGES,
defaultLanguage: DEFAULT_LANGUAGE,
};
return i18n(key,
data,
pluginOptions,
page,
);
});
// Needed to prevent eleventy from ignoring changes to our
// template files since they are in our `.gitignore`
config.setUseGitIgnore(false);
config.addPassthroughCopy({
'src/misc/favicon.png': 'favicon.png',
'src/misc/robots.txt': 'robots.txt',
});
return {
dir: {
input: 'src',
output: 'dist',
includes: '_includes/partials',
layouts: '_includes/layouts'
}
};
};
src/translations/index.js
module.exports = {
hello: 'Hello',
}
Here are the logs when I save a change in the src/translations/**/*.js file. We can see Browsersync reloading before writing the change and then reloading after writing is complete. But the change is not injected into dist/**.html
[start:eleventy] File changed: src/translations/index.js
[start:eleventy] [Browsersync] Reloading Browsers...
[start:eleventy] Writing dist/index.html from ./src/content/home.liquid.
...
[start:eleventy] Copied 4 files / Wrote 68 files in 0.90 seconds (13.2ms each, v0.11.1)
[start:eleventy] Watching…
[start:eleventy] [Browsersync] Reloading Browsers...
And here are the logs when I save in .eleventy.js we can see some diff.
[start:eleventy] File changed: .eleventy.js
[start:eleventy] Writing dist/index.html from ./src/content/home.liquid.
...
[start:eleventy] Copied 4 files / Wrote 68 files in 0.75 seconds (11.0ms each, v0.11.1)
[start:eleventy] [Browsersync] Reloading Browsers...
Has anyone encountered this or has a workaround?

Application modularity with Vue.js and local NPM packages

I'm trying to build a modular application in Vue via the vue-cli-service. The main app and the modules are separated projects living in different folders, the structure is something like this:
-- app/package.json
/src/**
-- module1/package.json
/src**
-- module2/package.json
/src**
The idea is to have the Vue app completely agnostic about the application modules that can be there at runtime, the modules themself are compiled with vue-cli-service build --target lib in a local moduleX/dist folder, pointed with the package.json "main" and "files" nodes.
My first idea (now just for development speed purposes) was to add the modules as local NPM packages to the app, building them with a watcher and serving the app with a watcher itself, so that any change to the depending modules would (I think) be distributed automatically to the main app.
So the package.json of the app contains dependencies like:
...
"module1": "file:../module1",
"module2": "file:../module2",
...
This dependencies are mean to be removed at any time, or in general be composed as we need, the app sould just be recompiled and everything should work.
I'm trying to understand now how to dynamically load and activate the modules in the application, as I cannot use the dynamic import like this:
import(/* webpackMode: "eager" */ `module1`).then(src => {
src.default.boot();
resolve();
});
Because basically I don't know the 'module1', 'module2', etc...
In an OOP world I would just use dependency injection retrieving classes implementing a specific interface, but in JS/TS I'm not sure it is viable.
There's a way to accomplish this?
Juggling with package.json doesn't sound like a good idea to me - doesn't scale. What I would do:
Keep all available "modules" in package.json
Create separate js file (or own prop inside package.json) with all available configurations (for different clients for example)
module.exports = {
'default': ['module1', 'module2', 'module3'],
'clientA': ['module1', 'module2', 'module4'],
'clientB': ['module2', 'module3', 'module4']
}
tap into VueCLI build process - best example I found is here and create js file which will run before each build (or "serve") and using simple template (for example lodash) generate new js file which will boot configured modules based on the value of some ENV variable. See following (pseudo)code (remember this runs inside node during build):
const fs = require('fs')
const _ = require('lodash')
const modulesConfig = require(`your module config js`)
const configurationName = process.env.MY_APP_CONFIGURATION ?? 'default'
const modules = modulesConfig[configurationName]
const template = fs.loadFileSync('name of template file')
const templateCompiled = _.template(template)
const generatedJS = templateCompiled({ `modules`: modules })
fs.writeFileSync('bootModules.js', generatedJS)
Write your template for bootModules.js. Simplest would be:
<% _.forEach(modules , function(module) { %>import '<%= module %>' as <%= module %><% }); %>;
import bootModules.js into your app
Use MY_APP_CONFIGURATION ENV variable to switch desired module configuration - works not just during development but you can also setup different CI processes targeting same repo with just different MY_APP_CONFIGURATION values
This way you have all configurations at one place, you don't need to change package.json before every build, you have simple mechanism to switch between different module configurations and every build (bundle) contains only the modules needed....
In an OOP world I would just use dependency injection retrieving classes implementing a specific interface, but in JS/TS I'm not sure it is viable.
Why not?
More than this, with JS/TS you are not restricted to use classes implementing a specific interface: you just need to define the interface (i.e. the module.exports) of your modules and respecting it in the libraries entries (vue build lib).
EDIT: reading comments probably I understood the request.
Each module should respect following interface (in the file which is the entry of the vue library)
export function isMyAppModule() {
return true;
}
export function myAppInit() {
return { /* what you need to export */ };
}
Than in your app:
require("./package.json").dependencies.forEach(name => {
const module = require(name);
if(! module.isMyAppModule || module.isMyAppModule() !== true) return;
const { /* the refs you need */ } = module.myAppInit();
// use your refs as you need
});

Node requiring directory rather than specific file

Are these two statements equivalent?
const deviceModule = require('..').device;
const deviceModule = require('../device');
I thought require needed a module (with our without path) as the parameter. How is it that a directory can be provided and what does the .device do?
Thanks to anyone who can help me understand node.js and javascript better.
require('..').device requires index.js from the parent directory, and then gets device from that file.
So if you had the following structure:
- index.js
- /foo
- - bar.js
With index.js having the following:
module.exports = {
device: "baz"
};
Then require("..").device in bar.js would give you "baz".
Here is the specification for loading a directory:
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
a. Parse X/package.json, and look for "main" field.
b. let M = X + (json main field)
c. LOAD_AS_FILE(M)
2. If X/index.js is a file, load X/index.js as JavaScript text. STOP
3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
4. If X/index.node is a file, load X/index.node as binary addon. STOP
So in your example, it will:
look for package.json and get the main property, and then load that if it exists
If step 1 does not exist, it will load index.js if it exists
If step 2 does not exist, it will load index.json if it exists
If step 4 does not exist, it will load index.node if it exists
You can use module require-file-directory.
1- Helps to require all the files only with name. No need to give absolute path of files.
2- Multiple files at a time.

Copy files with Yeoman generator doesn't work

I'm developing my own generator with Yeoman. When I try to copy some files, nothing happens. No error, the process continues until it reach the end, but no files are copied. The generator has a /templates dir with a bunch of html files, each file has a few html lines, at the moment quite simple stuff.
This is my copy method:
copyMainFiles: function(){
console.log('copyMainFiles dir:' + process.cwd() + '+++++');
console.log('file exists? '+fs.existsSync('_footer.html') );
this.copy("_footer.html", "app/footer.html");
console.log('footer copied');
this.copy("_gruntfile.js", "Gruntfile.js");
console.log('gruntfile copied');
this.copy("_package.json", "package.json");
console.log('package copied');
this.copy("_main.css", "app/css/main.css");
console.log('main.css copied');
var context = {
site_name: this.appName
};
console.log('all files copied');
//template method makes the replacement and then copy
this.template("_header.html", "app/header.html", context);
console.log('header template processed');
},
this is the console output:
$ yo trx
method 1 just ran
method 2 just ran
? What is your app's name ?
Kosheen
? Would you like to generate a demo section ? Yes
all dirs created
copyMainFiles dir:C:\cygwin\Applications\MAMP\htdocs\prueba-trx+++++
file exists? false
footer copied
gruntfile copied
package copied
main.css copied
all files copied
header template processed
running npm
and that's it. Never returns to system prompt.
Besides the fact that fs.existsSync returns false (the file exists: htdocs\generator-trx\generators\app\templates_footer.html ), if I try to copy a non-existent file I get the typical error.
Folders are created previously with no issue. There's a .yo_rc.json file with {} in the root of the destination folder. The Yeoman version is 1.4.8, working on Windows 7.
Is copy() the proper way to do this or is no longer valid? How can I copy a simple file in this scenario?
Beside the fact of I was using deprecated methods, the proper way to achive this task is as follow:
this.fs.copy(
this.templatePath('_bower.json'),
this.destinationPath('bower.json')
);
Not sure what your issue is, but you should read the Yeoman official documentation on how to handle files: http://yeoman.io/authoring/file-system.html
You're using old and deprecated methods.

How can I load multiple optimized requirejs modules dynamically in a production env?

I've started to play with require js on a dummy project. I now want to use the r.js script to build my project for production.
The context is this:
Main file called start.js is:
require([/* some stuff */], function (){ /* app logic */ });
which has an if that decides what I should require based on some condition.
The required files are either ModuleA or ModuleB
Both ModuleA and ModuleB have dependencies.
define([/*some deps*/], function(dep1, dep2...) {
/* app logic */
return { /* interface */
}
Everything works fine in development mode, before optimization and module concatenation.
When building with r.js I specify as module targets the following :
modules : [ { name : "start" }, { name : "ModuleA" }, { name : "ModuleB" } ]
The problem is that my ModuleA becomes :
define(dep1 ..);
define(dep2 ..);
define(ModuleA ..);
But nothings loads from ModuleA. The code from ModeulA in development loads and executes, the code after building loads but does not run.
How could I fix this problem?
UPDATE
http://pastebin.com/p1xUcY0A --> start.js
http://pastebin.com/dXa6PtpX --> ModuleA js-animation.js
http://pastebin.com/xcCvhLrT --> ModuleB css-animation.js no deps.
http://pastebin.com/j51V5kMt --> The r.js config file used when running the optimizer.
http://pastebin.com/UVkWjwe9 --> How the js-animation.js looks after running r.js. This is the file that has problems. I don't get the js-animation module from this file. The require does not return my js-animation object.
Edit:
After removing the .js at the end of the module definitions and in from start js, the optimized start.js is http://pastebin.com/LfaLkJaT and the js-animations module is http://pastebin.com/qwnpkCC6. In chrome, I get this error in my console http://pastebin.com/Hq7HGcmm
I believe the problem with your setup is that you end your module dependency names in .js. As per the docs:
RequireJS also assumes by default that all dependencies are scripts, so it does not expect to see a trailing ".js" suffix on module IDs. RequireJS will automatically add it when translating the module ID to a path.
If RequireJS sees a module name ending in .js it assumes that the module name is a path relative to the document. By ending your module dependency names in .js it works fine in development mode because RequireJS will go and load the file specified as a dependency. In your case it will load the file js/js-animation.js, see an anonymous define and load the module properly.
In production, your start.js module still requires "js/js-animation.js". RequireJS will load your optimized module at the path js/js-animation.js but now the optimizer has converted your anonymous modules into named modules (in this case "js/js-animation"). The result is the file will be loaded but no define'd modules within the file have a name that matches "js/js-animation.js" so in a sense your animation module is missing.
Solution / TL;DR: Remove the trailing .js from all your module dependency names (and your module definitions in the r.js config) and you should be fine. So your start.js should become (changes on line 4):
require([], function () {
var $html = $("html"),
animationModule = localStorage['cssanimations'] == 'true' ?
'js/css-animation' : 'js/js-animation',
$doc = $html.find("body");
console.debug("loading ", animationModule);
require([animationModule], function( animationModule ) {
animationModule.run({
target : $("div.flex")
});
} );
} );
Also note your may want to use baseUrl and paths in your RequireJS config to clean up module names (e.g. so you can remove the js/ prefix).
It seems this is problematic with the current require.js implementation. The way around it was to create a global mediator or mediator module and have all dynamically loaded modules call the mediator and announce themselves via an event. This worked for me.

Categories

Resources