Vuex, webpacker and sharing state between multiple packs - ruby-on-rails

I'm currently working on a rails project where we use webpacker. I want to be able to create small dynamic components and wrap these in packs. We want to be able to use these packs as elements within our server side rendered html. While this works (we currently have a pack for each component) I don't know what the best way would be for sharing the vuex store between these packs. I'm guessing this can be done through webpacker but i'm not sure.
the situation eg:
dynamic_component_one data-id="abc"
dynamic_component_two data-id="abc
= javascript_pack_tag 'dynamic_component_one'
= javascript_pack_tag 'dynamic_component_two'
Basically what i want to achieve is that
dynamic_component_1 and dynamic_component_2 share a common vuex store
My current solution exists of the following and feels very hacky. I register the Vue constructor and Vuex Store to the global window object to re-use them in different packs.
const vuex_store = new Vuex.Store({
strict: true
});
window['vue'] = Vue
window['vuex_store'] = vuex_store
if anyone could point me in the right direction i would greatly appreciate it.

Related

Vuex on global window instance

Ok so this is a pretty complicated question but I appreciate any help.
I have vue webpacker running on a rails application, I would like to use Vuex on it however all Vue components are unrelated, a solution I found online (here) was someone who added Vuex to the global window instance and imported that javascript into his main layout, I have done so and can see properly that a Vuex instance exists on my global window instance.
The code for that javascript I'm running is this:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const vuex_store = new Vuex.Store({
strict: true,
});
window["vue"] = Vue;
window["vuex_store"] = vuex_store;
Now my question is, in an unrelated vue component also running on my rails server, how would I import and use this Vuex instance?
Used it as a bus directly as I wanted initially.
window.vue.$on and window.vue.$emit anywhere

Rails: Accessing JS module methods from files served by webpacker

Context
I try to move assets in our application to webpack using Webpacker gem. Application is very big, so I need to do it partially.
What did so far...
I successfully managed to call the script using javascript_pack_tag
I export a super simple module:
# javascript/src/javascript/test.js'
const Direction = {
log_to_console: function(){
console.log('test');
}
};
export default Direction;
Then import it in the application entry point
# javascript/packs/application.js
import Test from '../src/javascript/test.js'
Test.log_to_console();
Finally rendering it in the layout:
# app/views/application.slim
= javascript_include_tag 'application'
The result is: "Test" string visible in the browser console.
The problem
Currently in the whole application we use Modules in views like this:
# app/views/assets/javascripts/test.coffee
log_to_console = ->
console.log('test');
#Test = { log_to_console }
# app/views/some/template.slim
javascript:
Test.log_to_console()
But after moving module to webpack I can't access the Test module anymore.
So my question is:
How to configure webpacker gem OR refactor the code above to make the log_to_console() method available in views/browser inspector?
Ideally it would be if we could also access them in old javascript files compiled by sprockets.
I figured out that solution for now. May be helpful for anyone that encounters that problem.
If anyone finds better solution, I would be glad to see it here ;).
For now all our modules/libraries that are needed to be visible in views/other coffee files, I just set as globally available via the window object.
import Foo from '../src/javascript/foo.js
window.Foo = Foo
I know it's ugly anti pattern, but works well as temporary solution until we update our scripts behave more like independent packs.

Using ASP.NET Javascript Bundles from the controller

I realise this breaks the MVC pattern, but there is a viable reason for doing it this way in an application I am currently building :)
What I am trying to do is output a JavaScript bundle directly from the Controller rather than via a link via a View.
So for example I have a bundle called "~/jQueryPlugin" what I'd like to do is something along the lines of
return this.JavaScript(BundleTable.GetBundle("~jQueryPlugin").BundleContent)"
However for the life of me I cannot figure out what the BundleTable.GetBundle("~jQueryPlugin").BundleContent part should be in order to get a string representation of the combined minimized bundle.
Any help would be appreciatedĀ·
In the 1.1-alpha1 release we added a new Optimizer class which should allow you to more easily do this. Its intended to be a standalone class that's useable out of side of ASP.NET hosting, so setting it up will be slightly different.
You can get the bundle contents out via something like this:
OptimizationSettings config = new OptimizationSettings() {
ApplicationPath = "<your physical path to the app>",
BundleSetupMethod = (bundles) => {
bundles.Add(new ScriptBundle("~/bundles/js").Include("~/scripts/jqueryPlugin.js"));
}
};
BundleResponse response = Optimizer.BuildBundle("~/bundles/js", config);
Assert.IsNotNull(response);
Assert.AreEqual("<your bundle js contents>", response.Content);
Assert.AreEqual(JsMinify.JsContentType, response.ContentType);
The next release should be fleshing this scenario out more, as it is needed for build time bundling integration with Visual Studio.

How can I move multiple Pylons Applications into a single Composite Application?

We have several single Pylon websites running but would like to make these more easily reusable.
There is a concept of a "Composite Application" inside pylons, but there seems to be limited instructions on how to achieve this.
Has anyone done this or is aware of a good tutorial on "How to convert multiple pylons apps into a composite app?" ?
I've tried - perhaps too optimistically - to simply copy an existing app into another app and fiddle with the development.ini file, but this does not seem to work. (I'm getting the error "pkg_resources.DistributionNotFound: wiki" in that case)
Thanks
This is done by modifying the WSGI pipeline to dispatch a request to different applications based on request properties (usually URL). The simplest way to modify the pipeline is by PasteDeploy (the package that controls your INI files).
[composite:main]
use = egg:Paste#urlmap
/foo = foo
/bar = bar
/ = baz
[app:foo]
use = myapp#main
[app:bar]
use = yourapp#main
[app:baz]
use = myapp#baz
This creates a composite application that dispatches to different endpoints based on the URL prefix.

How to reference a JavaScript file in Lib from an HTML file in Data?

I decided to give Mozilla's Add-on Builder a try. My directory structure looks something like this:
The problem is that the file popup.html needs to reference stackapi.js. But I have absolutely no clue how to do that. Looking through the Mozilla docs, there seems to be a way to do the opposite:
var data = require("self").data;
var url_of_popup = data.url("popup.html");
This allows scripts in Lib to access data files in Data. But I need to do the opposite.
In add-ons built with the Add-on SDK (and the Builder is merely a web interface for the SDK) web pages cannot access extension modules directly - they don't have the necessary privileges. If you simply need to include a JavaScript file from the web page then you should put that file into the data directory. However, it won't have any special privileges then (like being able to call require()).
You don't tell how you are using popup.html but I guess that it is a panel. If you want that page to communicate with your add-on you need to use content scripts. Put a content script file into the data directory, assign it to your panel via contentScriptFile parameter. See documentation on content scripts, the content script will be able to use self.postMessage() to send messages to the extension, the extension can perform the necessary operations and send a message back then.
You can get the url of the stackapi.js file by navigating up from the /data folder and back down the /lib folder like so:
var url=require("sdk/self").data.url("../lib/stackapi.js");
Then use that resource url in the contentScriptFile parameter when attaching scripts to what I assume is going to be popup.html.
You'll need to check which environment you're currently in to determine if you need to add any references to the exports object to make them accessible from within the addon.
if(typeof(exports)!="undefined"){
exports.something=function(){...};
}
Had to go through the same scenario, but solution by jongo45 does not seem to work anymore. Somehow found a solution which worked for me. Posting below as it might help someone in need.
Below code obtains list of all files under "lib/subdir".
const fileIO = require("sdk/io/file");
const fspath = require("sdk/fs/path");
const {Cc, Ci} = require("chrome");
const currDir = Cc["#mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryServiceProvider)
.getFile("CurWorkD", {}).path;
const listOfFiles = fileIO.list(fspath.resolve(currDir,'lib/subdir'));

Resources