Aurelia external resources - npm

I'm looking for the best way to arrange my code base with common resources shared between different projects. I have three aurelia apps. In each one, I added some resources in its resources folder (custom elements, attributes, etc). When I needed one already wrote in another project, I just pasted it. Now I have time to refacto, I'd like to move all this resources in a dedicated repository. Then I want to be able to pick only the resources I need in each project.
I've tried by putting all me resources in a repo with a gulp build task from aurelia skeleton which allow me to build AMD modules of all my modules. Then, I've been able to load some modules individually by adding them in aurelia.json. For exemple for an attribute:
{
"name": "aurelia-resources-progress-button",
"path": "../node_modules/SHG-aurelia-resources/dist/amd/resources/attributes",
"main": "progress-button"
}
or a custom element:
{
"name": "aurelia-resources-avatar-upload",
"path": "../node_modules/SHG-aurelia-resources/dist/amd/resources/elements/avatar-upload",
"main": "avatar-upload",
"resources": [
"avatar-upload.html",
"avatar-upload.css"
]
}
It worked like a charme but it failed for a value converter which import a module from relative path.
The file is located in :
"projectRoot/node_modules/SHG-aurelia-resources/dist/amd/resources/value-converters/duration-format.js",
it import from '../utils./strings'
and
I get the following error when I au run:
"Error: ENOENT: no such file or directory, open
'/Users/hadrien/Documents/dev/SportHeroes/united-heroes/src/resources/utils/strings.js'".
The strange thing is when I require a relative module from a template (like in my progress-button custom attribute) there is no problem.
I don't want to make a plugin because I don't want to load every modules of my repo. What I'd like, if it is possible, would be to be able to set .feature('../node_modules/path/resources') and load them like I load my local resources.
What should I do ?

I'm answering the question as reworded in the comments above.
If you have an npm package, you can simply require in resources from it using a require element. This npm package could package itself as a plugin, and you simply choose not to load it that way as you only want a subset up the stuff it provides.
I've created a set of sample projects that show this off: https://github.com/AshleyGrant/sample-app-so41961759
This application has a dependency on https://github.com/AshleyGrant/sample-resources-so41961759/
This dependency packages itself as a plugin, but it also can be consumed piecemeal as I am doing in the application by only using one of the two resources the plugin has. Note that the other resource isn't loaded since I'm not using it.
This is what it looks like in the app when I pull in a resource from within the dependency:
<template>
<require from="sample-resources-so41961759/custom-elements/my-echo"></require>
<h1>${message}</h1>
<my-echo say="Echo!"></my-echo>
</template>

Related

How to turn multiple vue components into one single npm package?

I was told by the project manager at the company I work for to take all the global components of a vue project we're working on and turning them into a single npm package that anyone working on the project can import and start using. essentially I have to take the global components and turn them into a component library like vuetify which is installed using npm and than imported from node modules directory.
I was wondering if you guys could point me in the right direction on how to achieve this. thanks in advance.
So, regardless of the implementation, the main thing you need is following this guide on how to create an npm package
https://docs.npmjs.com/creating-and-publishing-private-packages
Then
You create an src folder.
In the src, you will create a folder named "components" with all your -duh- components.
In the src folder, you will also create an index.js file, from there you will export your components.
export { default as VDataTable } from './components/VDataTable.vue'
// ...etc
Option1
If you use a bundler for your projects, and you know by a fact that all your codebases will use a bundler, you can simply create a folder with a package.json.
In your package.json then you will
"module": "src/index.js",
"main": "src/index.js"
In this scenario, you are letting your main project bundler (which is using the package) transpile all the packages for you, (babel, single file components)
Option 2
In case you have absolutely no clue of the nature of the projects which can use your library you will need a bundler for your components.
An example can be Rollup.
I suggest these 2 guides.
https://rollupjs.org/
https://rollup-plugin-vue.vuejs.org/
Long story short, Rollup will transpile for you the files you requested (js and css), and you will have to make them available from your package.json
"module": "src/dist/library.esm.js",
"main": "src/library.common.js"
And then you can release your package. Possibly privately or you might get fired :P

Creating a single Vue component inside a larger project

I have a PHP project that uses Kirby CMS. I also use Gulp for building my assets. Now, I need to add a calculator on the homepage that is complex enough to justify the usage of Vue. How would I incorporate Vue in my project without introducing a ton of new tooling? All I want is a simple Single File Component basically. I have:
<div id="calculator"></div>
and I want the component to be rendered there. Nothing more.
After some consideration, I came up with the following options but found issues with each of them:
Use the Vue CLI for instant prototyping. That's the closest solution for my use case, but I can't easily develop the component. If I use vue serve, I get to see the component isolated in a new page. The issue lies in the fact the component isn't a part of my project's page. It's not affected by its stylesheets, layout, and other scripts. I can't know if it'll work properly once I build it and view it in my project. Running vue build on each change would be pretty painful and time consuming. Sadly, vue watch isn't a thing, which leads me to:
Creating a project and using Vue CLI Service. If I create a project, I'd be able to run vue-cli-service build --watch and have my component automatically refresh on each change of its source file. While developing the component, I simply make a change, wait for it to compile, and refresh my project in the browser to see the modified component in action. While that would work, it introduces a bunch of node_modules inside my project, along with a package.json. I feel that's too much for just a single component. It would pollute the project more than I'd like:
assets/
js/
build/
calculator/
dist/
node_modules/ # modules here
public/ # I don't need that
package.json # package here
package-lock.json
App.vue
scripts/
main.js
content/
site/
node_modules/ # modules here as well
panel/
package.json # package here as well
package-lock.json
index.php
I would basically have a project within a project.
Use vueify to compile the component with Browserify and Gulp (which I already use). While this appears OK, vueify is deprecated and not supported. Besides, I'd have to add a bunch of stuff to my gulpfile.js in order to use Babel + ESLint for the component.
How do I set up Vue in such a way that I'm able to develop a very simple component as a part of a larger project with as little friction as possible?
If anyone has dealt with a similar problem, how did they solve it?
I ended up using the second approach I mentioned in my question with one small twist - I initialized the Vue project in my main project. I merged them.
I opened the parent folder of my project in a terminal.
I ran vue create my-project where my-project was the actual folder name of my project. The CLI asked if it should overwrite the project or merge it. I chose merge.
After the project was created, my old package.json was overwritten and only had the Vue dependencies listed in it.
I reverted my old package.json and installed these packages: #vue/cli-plugin-babel, #vue/cli-service, vue-template-compiler, and vue.
I added the following npm script in my package.json:
"scripts": {
"calculator": "vue-cli-service build assets/js/calculator/main.js --watch --dest assets/js/calculator/build"
}
Result
My project's folder structure remained the same, except for a few new packages in node_modules. I put my component files in assets/js/calculator/. There, I have main.js which is the main component script, and build which is a folder containing the processed component.
I have:
<div id="calculator"></div>
in my page, and:
<script src="/assets/js/calculator/build/app.js"></script>
in the footer. When I open the page, the component is rendered correctly.
To modify the component, I simply run npm run calculator in a terminal, which spins up the CLI service. It monitors the main.js file and builds the component on each change. Once the build is complete (which happens in under a second), I refresh the page and the updated component is there.
Conclusion
I believe that's the smoothest way to handle this use case. It didn't bloat the project, all dependencies were listed, and the development experience is great. The part where my package.json got overwritten was a bit concerning, but other than that - it worked perfectly. If there's a better way to do this, please leave an answer!
This is probably not the answer you're looking for but if I were you I'd look into inline templates and x-templates as they seem well suited to your use case.
Also have a look at this blog post. It offers a nice write up about the different template authoring methods in Vue and their pros/cons.

How to deliver an aurelia library for consumption by aurelia CLI based app

I'm building a library of aurelia custom elements for use by several different aurelia apps and am running into trouble getting the custom element html hooked into the app bundle properly with the CLI process.
I'm currently thinking that the library will be part of package.json and thus listed under node_modules/my-lib. What should the delivered .html format be
<template>...</template>
or should it be delivered in required format
define('text!my-lib/component1.html', ['module'], function(module) { module.exports = "<template>\r\n ...
If the former - what do I put in aurelia.json to get it to be included correctly in the vendor-bundle?
If I do resouces['../node_modules/my-lib/**/*.html'] in my-lib dependency section - it gets included as html in a js file which throws an error.
If I add as source to the vendor-bundle or using my own bundle my-lib-bundle.js
"source": [
"[../node_modules/my-lib/**/*.js]",
"../node_modules/my-lib/**/*.{css,html}"
],
Nothing gets included then except the 'main' listed in the one dependency.
If I add to the markupProcess (which seems more linked to the app and not a library)
"markupProcessor": {
"id": "none",
"displayName": "None",
"fileExtension": ".html",
"source": [
"src\\**\\*.html",
"..\\node_modules\\my-lib\\**\\*.html"
]
},
I get the html correctly added to app-bundle but has the wrong path because it includes the '../node_modules' in the define so it's not found when the app attempt to use it.
I'm not using the CLI to build my lib as I want the app to only include pieces it uses. So the JS is built and delivered in AMD format, but I wasn't sure the process to go through with HTML?
Suggestions?
There is a skeleton plugin repo # github
https://github.com/aurelia/skeleton-plugin
With build scripts and all

Managing Dependencies in SailsJS

How can I manage dependencies in a Sails.JS based project. There is a really neat feature which automatically links assets from the assets folder into the relevant templates, however, to get these files, e.g Angular, Bootstrap, Material-Design etc. I like to run bower / npm install. But then the resources are in the bower_compnents file and can't be linked to. How can I work around this to get file installed by package managers to be included in Sails.JS's default mechanism?
You have the option to change the location of the bower components with a .bower.rc file.
Example .bower.rc
{
"directory": "assets/components/"
}
It is not a good idea to automatically link components, there are many .js/.css files that must not included together (eg. lib_name.js and lib_name.min.js).
You have to include them manually like this (tasks/pipeline.js)
var jsFilesToInject = [
'components/lodash/lodash.js',
'components/moment/moment.js',
'components/moment/locale/el.js',
'components/angular-moment/angular-moment.js',
'components/re-tree/re-tree.min.js',
'components/ng-device-detector/ng-device-detector.js',
// Load sails.io before everything else
'js/dependencies/extend.js',
'js/dependencies/sails.io.js',
// Dependencies
//'js/dependencies/**/*.js',
'js/my-app-bootstrap.js',
// load my controllers
'js/angular/**/*.js',
'js/my-app.js',
];

How to load a bootstrap js file in my case?

I have a question regarding loading the dependencies using Bower.
I have bower.json like
{
"name": "My project",
"version": "0.1",
"dependencies": {
"angular": "~1.2.0",
"angular-bowser": "~0.0.1"
}
}
//I want to add alert.js dependency
I was hoping to add a custom bootstrap JS file that is only for alert. I am not sure how to add the custom file since I can't run bower install to install the custom file.
Any tips? Thanks a lot!
You add bootstrap as a Bower dependency. Then in whatever other tool you're using to either generate <script> tags or generate a single concatenated JS file, you add Bootstrap's alert.js (and any other Bootstrap jQuery plugins that Alert depends on) to the list of required JS files.
Speaking more generally, Bower is an pretty minimalistic package manager, to the point that it is arguably not very useful, as it provides relatively little metadata and leaves many issues to instead be dealt with by other tools or by the user manually. Hence, what you're asking for here goes beyond the realm of Bower itself.