I noticed that somehow there is no packages folder in my newly created Meteor 0.9 project. This means that it must be using package from the ~/.meteor things. However, I cannot work like this as I am hopping between machines all day and I would like the package to stay locally; like in the project folder itself.
In the previous Meteor 0.8.3 project, I manually created packages folder in the project and when I add package it went inside there (for example i can find collectionFs inside package/ in the project directory).
I want it to be like this. How can I do this safely?
You can still drop packages into the top-level "packages" directory inside your project and then run meteor add like usual. These packages are just treated as app-specific packages. Here are the docs about using packages. The relevant bit is quoted here:
In addition to the packages in the official Meteor release being used by your app, meteor list and meteor add also search the packages directory at the top of your app.
I think the idea was to delineate the stand-alone application code from 3rd party libraries. As a package author, this means there are less forks of my library with subtle changes floating around on Atmosphere. It also makes your apps a bit less prone to bugs (given the packages are stable), and encourages better package maintenance.
If you want to use local packages though, here is a good walk-through.
For NPM packages, also check out meteorhacks:npm | github
For the collectionFS, you have to use meteor 0.6 version.
You have to add new release file of meteor 0.6 version.
https://github.com/CollectionFS/Meteor-cfs-example-filemanager
Related
I have been looking for a way to mostly share some code between projects specifically for SPFX and fluent ui. We found 3 main ways to do that.
1.
Creating a component library is the way that seemed least complicated cause it uses the same infrastructure and do all building without the need to configure it.
But this adds some issues, we need to built and manually link the solution locally to make it work, this will also work if we put in a repo. so this is mitigated.
The second is that implicitly this will also require the fluent ui and react. Plus having to place it inside a SPFX component library project.
2.
I saw some promise using paths in ts and this works fine while using the ts compiler. It will go to the folder that your proj is referring and build it at calling time. which is great. But it did not work in SPFX.
3.
Another way was to have a post install to sync the folders which seems easy enough but I wonder how practical this is plus how people are doing it, if they are, how.
All I wanted to figure out now is a way to take my component code and share as if they were in a folder of my src or a simple extension of the code. No need to have extra dependencies or build steps, just the code that can be used as a ts/tsx file. ex:
shared lib:
//assuming I have react and fluentui already installed for the project.
import button from 'fluentui';
export const fancyCustomButtom = (props) => {
return (<Button text="Standard" />);
};
src project folder:
import {fancyCustomButtom} from 'shared-lib'
It is fine if it needs to build the files before we can use it but can we do it at build time or when the package is installed? also wouldn't it increase my bundle size by making both module dependent on things already available (react, fluentui)?
Given the way Microsoft have architected the loading of bundles in SharePoint and Teams - I believe an SPFX component library is the best way to share code between different solutions, particularly if you are looking to minimise bundle size...
Imagine you have a library for something re-usable: a form, a set of standard branded components - something of that nature. You could put your shared code in repos and add references to it - either by publishing your own repo publicly or using the npm install git+https://yourUrl syntax; but what effectively happens there is that your code is pulled down in to node_modules for each project, and any referenced module code is included in your bundles. If you have two, three, four or more webparts on the same page - using those same libraries, you're multiplying how many times that code is included on the page.
If you follow Microsoft's guide on setting up a component library project however, your npm link commands allow your types to be recognised in consuming projects without needing to actually include the bundled distribution code. You can deploy your library code once to the App Catalog, and if it's referenced in other solutions -- it's loaded on pages as needed: once.
I have found the development experience to be quite flaky at times, but it does work. When I run gulp clean on my library code, or come back to it after some time, I sometimes find that I need to run npm link and npm link my-project-name again as per the instructions in the above tutorial. Whenever you run gulp build on your library, you should also rebuild the project that consumes the library, either by using gulp build / bundle or by saving a file (if you're running gulp serve). This process works well for developing, and once it comes time to deploy, all you need to do is add a named reference to your library inside package.json and then deploy both .sppkg files to your App Catalog.
In terms of your last question re: bundle size - react is not actually included in the dependencies for an SPFX library project, but you will find it's available to use. When you build your library, if you take a look in the generated javascript in your dist folder, you will see it's listed as one of the dependencies for the webpacked content along with react-dom and ControlStrings. It's on line 1.
office-ui-fabric-react is included as a devDependency thanks to the #microsoft/sp-webpart-workbench package that gets scaffolded with all SPFX projects - and if you check your library's dist javascript, you will see that included components are being webpacked and included in your bundle. I'm not entirely sure if when you pull this code in to your consuming project, whether webpack then tree-shakes to de-duplicate and ensures only necessary code is included: I don't know. Someone else may be able to illuminate us there or provide a more accurate explanation of what's going on... I will update this response if anyone comments to let me know.
And finally, this is more of a personal way of working, but it may be worth consideration:
When developing a library, I sometimes reference it in other projects via a local npm install ../filepath command. This ensures that when I install the library as described, the consuming project installs any necessary dependencies. I'm able to tweak both projects if I need o. When it comes time to deploy, I commit my changes to both projects, deploy my library code to the App Catalog, and then npm uninstall the library from the consuming project and add a reference as described in the above tutorial. When I deploy projects that use my library, they just work.
I recently developed a library that uses pnpjs, in particular the #pnp/sp library that is used to talk to SharePoint. If you look at the Getting Started guide for that library, they expect you to pass a reference to your Application Customizer or Web Part context during setup, or explicitly set things up using a base URL and so forth - and of course, a library doesn't really have a page context of any sort - the whole point of this code is that it's reusable. So that poses a challenge. My solution was to do the setup in the consuming web part(s) and ensure that they pass a reference to the sp object (which is of type SPRest) to any code or components that exist in my library. My library has peerDependencies on those pnp libraries so that the code isn't duplicated in consuming projects. Sometimes you have to think about what your library needs to include in its bundle and what you expect consuming solutions to already have, and maybe find ways to ensure things aren't included that aren't needed.
For example, in the scenario you talk about, you may want to ensure fluentui or office-ui-fabric-react are only devDependencies or peerDependencies for your library. As long as your library and the project(s) consuming your library both use the right version(s) you shouldn't have any trouble, and you can document any pre-requisites with your library documentation. You can check which versions of these libraries are installed per the SPFX version you are currently using ie. SPFX v1.11 or v1.12 etc. Just run npm ls <packagename> to get a breakdown, or check your package.json file.
We have built a small-ish application using Aurelia, and would like to be able to integrate the app into a larger codebase. For example, it may be desirable to publish the Aurelia app on NPM, so other projects could integrate our code.
How can we build/publish the Aurelia app, so that it can be instantiated in a larger JavaScript application?
Typically, you wouldn't publish an entire Aurelia application to NPM, rather you would push plugins to NPM.
The simplest way to learn how to do this is to follow the example of the various Aurelia repos. We build the code in to multiple formats, but the most important are AMD and CommonJS (which is more important for your company is dependent on what tooling your company is using). Once you've built the code, the next step is to make sure your package.json file is set up correctly. It's best to copy the example of what we're doing in our own repos.
I would start by looking at either the dialog plugin or the templating-resources plugin. Both of these show good examples of how to publish your Aurelia plugin to NPM, whether it is a public or private npm feed.
https://github.com/aurelia/dialog/blob/master/package.json
https://github.com/aurelia/templating-resources/blob/master/package.json
Both of these plugins are set up to support Webpack, JSPM/SystemJS, and the Aurelia CLI out of the box.
I totally agree with #Ashley in not publishing larger applications to the global NPM registry. The big advantage of it is the simplicity of all that small packages which can be used to build large applications.
If you feel you got some reusable code, put in an own package and publish it.
Anyway, to give you an answer which does not require you to publish your complete app: you can include a complete repository (which is probobly what you are lookig for) in a different application via NPM.
npm install git://github.com/somegit/hubrepo.git
Or directly via the package.json:
"dependencies": {
"private-repo": "git+ssh://git#github.com:somegit/hubrepo.git#v1.0.0",
}
You can also do something similiar e.g. using JSPM. This would be simply:
jspm install your-app=github:OrgOrUser/your-app#your-branch
If you are facing long relative paths in your imports now, depending on your tooling, you may be interested in something like e.g. Resolving require paths with webpack which shows how to alias relative paths.
Sources/Links:
How to install a private NPM module without my own registry?
npm install private github repositories by dependency in package.json
TL;DR Summary
(I'm using Lodash as an example here, but it could be any other package)
In addition to using Lodash for its own purposes, my application also needs to import JavaScript from an NPM package that I created. The JavaScript in this package relies on Lodash as well. It's possible that each codebase may have installed a different version of Lodash. If JavaScript in my application and JavaScript in the installed package both import the same Lodash functions, then I want to avoid having to bundle two different versions of the same function. I understand that NPM is able to resolve the dependencies and that nothing will break, but the size of my application's JavaScript bundle will continue to grow as each codebase uses functions from different versions of the same libraries. It sounds like the only way to keep the versions in sync is to continuously monitor them and upgrade manually when appropriate, or to use the version provided by the installed package directly, without ever installing it into my application's own package.json. Is doing the latter a bad idea and is there no better way?
Original Question
At my company, we've created a Git repository that houses most of our UI component code. This repository also contains a static site generator, which transforms our UI component code into a "living style guide" website. The purpose of this website is to document and showcase our UI components on the web (similar to how PatternLab works).
We also distribute this code via NPM, so that it can be shared across multiple projects. Each project installs the NPM module as a dependency, then imports the SASS and JavaScript files contained within. The JavaScript has been written in ES6 and has not been bundled or transpiled. We've intentionally chosen not to distribute browser-ready code. Instead, each project is responsible for compiling its own SASS and bundling/transpiling its own JavaScript.
Most of our UI component JavaScript is simple and does not depend on any third-party libraries, so it's easy to import into our projects. However, some of our newer, more complex components rely on NPM packages such as Lodash, which presents a problem.
Obviously, we need to install Lodash in order for the static site generator to showcase our Lodash-reliant components inside of a web browser. Similarly, projects that consume the NPM package will also need to install Lodash, in order to create instances of these same components. This forces us to install Lodash twice: once in the UI component project, then again in the project that consumes the NPM package. This is problematic because the two projects could potentially install different versions of Lodash, which could lead to compatibility issues and/or increase the size of our JavaScript bundle.
One solution that I've discovered is to include Lodash under dependencies instead of devDependencies, in the UI component project. This way, when external projects install the UI component NPM module, Lodash will be installed along with it. This gives the project "free" access to Lodash without needing to explicitly install it itself. This is possible because NPM installs packages in a single, flat directory hierarchy, so it doesn't seem to matter if your project installs a package directly or if one of its dependencies exposes it as a dependency in it's own package.json. This eliminates version conflicts, since you don't have to install the package twice.
My question is, does this violate NPM best practices or is this how NPM is intended to work? After reading the NPM documentation and Googling for answers, it doesn't seem like this should be a problem. However, if what I'm suggesting is a bad idea, how else can I accomplish what I'm trying to do?
Here's a quick visual aid:
main.js
node_modules/
lodash/
foo/
bar.js
node_modules/
lodash/
main.js imports and uses Lodash. It also imports foo/bar.js, which uses Lodash too, but a potentially different version. Both files are ES6. main.js gets bundled and transpiled before being sent to the browser.
if is something you are directly using you should specify it in your package.json. it will be installed anyways but this way it will ensure that if your dependency removes that package as a dependency your project won't break
Context
I'm using the aldeed:autoform package and found a couple bugs & filed PR for it(https://github.com/aldeed/meteor-autoform).
Aldeed being the only maintainer of a lot of popular packages ends up being the bottleneck for merging PR & following up with issues.
My solution was to fork his project & published my fork on atmosphere.
Naively, i just removed his package meteor remove aldeed:autoform and tried to add mine: meteor add metakungfu:autoform
When i load my app, i get the following error:
Package['aldeed:autoform'] returns the expected object, even though i removed the package.
For sake of completeness, i do use a bunch of other packages that depends on aldeed:autoform and my guess is that this is the reason why aldeed:autoform package is still present.
Questions:
What's the right way to use a fork of a package, when that package is dependency of other packages?
Is this the right way to solve my problem?
I've end up using mgp to manage the packages.
In order to solve my problem, i had to do two things:
First, add a git-packages.json in the root of your project that looks like this:
➜ cat git-packages.json
{
"aldeed:autoform": {
"git": "git#github.com:gregory/meteor-autoform.git",
"branch": "dev"
}
}
This will work locally, but if you deploy to heroku, the buildpack will need to install mgp & install the dependencies.
I just opened a PR to fix this
Fork all the dependencies and make them point to your fork.
Instead of publishing your own version of aldeed:autoform onto Atmosphere, you should rather use it as a local package, keeping its name intact. Meteor will look first for your local packages, before trying to fetch from Atmosphere.
That way, all your other packages that depend on it will use your local version.
To do that, see: Why does Meteor's aldeed/meteor-tabular package get stuck processing and never render a result?
Reference: Meteor Guide > Build > Writing Atmosphere Packages > Overriding packages with a local version
I have standard node.js REST API. And I want to use some meteor's packages like Minimongo, Tracker, Blaze (any Meteor's package)
There a lot of articles how use npm modules in Meteor but I have opposite task. Should I create some wrapper to make it possible to use as a Node modules?
There is similar question: How to use Meteor packages outside of Meteor?
but nobody answer.
this is a good question, but you cannot just use require for a meteor in npm. You also cannot use Drupal modules in in plain PHP, it will not work as in the context they are written for. Yes you can use npm packages in Meteor, but only because Meteor is build on top of Node, not vice-versa.
Meteor has its own packaging system, because Meteor Packages are Isomorph, they have the ability to share their code on client and server, like the SimpleSchema Package or many others. To make it simple for developers to use it, it's an complete encapsulated system.
But to your question. There are a some of really valuable "ports" of Meteor Packages to plain npm architecture. For example you mentioned Tracker, so there is a npm package for that.
Tracker:
https://github.com/eface2face/meteor-tracker
(There is no Readme, but I guess it should be used, like Meteor Tracker, right?)
Minimongo:
https://www.npmjs.com/package/minimongo-standalone
... just to mention some...
To port a package you just need to extract the needed code, which don't depend on Meteor and other meteor packages and create a npm package of them.. So the code still behaves the same.. Just look at the Tracker code
You have to decide, why do you need meteor packages for your node/express application? And maybe there are already some better solutions in the npm world itself. If you really depend on major meteor packages, then just use Meteor ;)
I just get the same issue so i look around perhaps it's too late
However o found this https://www.npmjs.com/package/meteor-client-packages-meteor
Perhaps it could be helpful now
Or use this which the author recommends https://www.npmjs.com/package/meteor-webpack-client
Both are available..