I am trying to build a Meteor package that generates static files for the client to consume. I cannot seem to figure this out. I have tried to write files to the public directory as well as adding assets via compileStep.addAsset, but neither appear to work.
Is there a standard way to do this?
I see a very similar question, but it is a bit old & does not appear to work anymore.
Until you find a better solution consider using collectionFS. You can serve from either filesystem or gridfs as shown below. This way you can avoid worrying about mapping urls to the files because collectionFS does it for you.
Images = new FS.Collection("images", {
stores: [new FS.Store.GridFS("images", {})]
});
Images = new FS.Collection("images", {
stores: [new FS.Store.FileSystem("images", {path: "C:/uploads"})]
});
Inserting and linking to is handled with the following.
Images.insert(file, function (err, fileObj) {
});
Images.findOne().url();
Add the following packages depending on your usage.
meteor add cfs:standard-packages
meteor add cfs:gridfs
meteor add cfs:filesystem
Related
I have an Angular 2 application in which i wish to use wrapbootstrap. I do however have a problem with the fonts (bootstrap, font-awesome, google) as i do not know how to implement them.
When using the css file for wrapbootstrap is says it cannot find font awesome:
"Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:8000/fonts/font-awesome/fontawesome-webfont.woff2?v=4.4.0"
I cannot make sense of this as i can see the missing file(s) in resources in the chrome console on that exact address.
The font files are currently in a folder vi the following relative path from the css (application.css) file using them:
Which fits the required path in the css file:
I hope someone out there can provide some guidance as i am lost.
Thanks in advance
Solved
the problem was apparently the location of my fonts folder.
my file structure are as follows:
and i had firstly added the fonts/ relative to where the application.css file was. It had to be located in the root of my app (src)
Adding fonts installed with package manager is quite often a task. For instance, using font-awesome or any other similar library is a typical task one will need.
For this purpose, you can go through the following steps:
In tools/config/project.config.ts:
...
export class ProjectConfig extends SeedConfig {
PROJECT_TASKS_DIR = join(process.cwd(), this.TOOLS_DIR, 'tasks', 'project');
FONTS_DEST = `${this.APP_DEST}/fonts`;
FONTS_SRC = [
'node_modules/bootstrap/dist/fonts/**'
];
...
Create a file tools/tasks/project/build.fonts.ts:
import * as gulp from 'gulp';
import Config from '../../config';
export = () => {
return gulp.src(Config.FONTS_SRC)
.pipe(gulp.dest(Config.FONTS_DEST));
};
In gulpfile.ts (or in seed.tasks.json for newer versions of the Seed)
// Build dev.
gulp.task('build.dev', done =>
runSequence('clean.dev',
'tslint',
'build.assets.dev',
'build.fonts', // Added task;
'build.js.dev',
'build.index.dev',
done));
// Build prod.
gulp.task('build.prod', done =>
runSequence('clean.prod',
'tslint',
'build.assets.prod',
'build.fonts', // Added task;
'build.html_css.prod',
'build.js.prod',
'build.bundles',
'build.bundles.app',
'build.index.prod',
done));
// Build test.
gulp.task('build.test', done =>
runSequence('clean.dev',
'tslint',
'build.assets.dev',
'build.fonts', // Added task;
'build.js.test',
'build.index.dev',
done));
src
The common use of grunt-wiredep is to scan through your given HTML and inject the relevant dependencies into that HTML.
I'm looking to instead get the JS & CSS dependencies, in the order as determined by wiredep, concat them into a single JS and single CSS file and write those files.
I can see that wiredep itself is happy to return an object with an ordered list but the syntax for getting Grunt to write these into files is beyond me.
Does anyone know if this is possible and what the syntax would be? The first thing that all grunt-wiredep tasks start with is a source HTML file and that's not what I'm looking to do.
Any advice appreciated!
Thanks for your solution!
I've added some extra details, so it works out of the box:
//Put all bower files in one file
grunt.registerTask('bower-bundler', function() {
//Point to the file which source you need to bundle
var result = require('wiredep')({
src: ['index.html']
});
//Set grunt config for concat task based on result.js and add an output file
grunt.config.set('concat.withWiredepJS', {
src: [
result.js
],
dest: 'build/lib_min.js'
});
//Run the task right away
grunt.task.run('concat:withWiredepJS');
});
So the way I finally overcame this with a colleague is remarkably simple.
I set up a new Grunt task to get the object I needed from the node Wiredep process as here:
grunt.registerTask('bower-bundler', function () {
var result = require('wiredep')();
grunt.config.set('concat.wiredepCSS.src', result.css);
grunt.config.set('concat.wiredepJS.src', result.js);
});
The grunt.config.set() allows you to set a task's source outside of it's config block.
In a meteor project I maintain there has been cause to look at moving away from gridfs as the backend to CollectionFS and moving towards s3.
One thing I would be keen to do is migrate images / files currently stored using the gridfs collections.
Has anyone attempted this before? I can't find any guides or even suggestions.
My thinking right now is along the lines of;
Create a new collection backed by s3
Iterate over old collection pushing the data into s3
Update code to point to new collection
Does this seem sound?
I just did this!
You're basically right, here's how I did it. Migration is a pretty easy process. I've gone from GridFS to S3.
1) By adding new FS.Store.S3("store_name",{}), CollectionFS automatically clones the meta data of existing files in the old store for your new store. But, all file sizes are zero in this new store.
Images = new FS.Collection("images", {
stores: [
new FS.Store.S3("s3images", {}),
new FS.Store.GridFS("images", {})
]
});
2) While you have both stores in place, you need to manually migrate the content using the piping as referenced here https://github.com/CollectionFS/Meteor-CollectionFS/wiki/How-to:-Convert-a-file-already-stored.
if(Meteor.isServer) {
Images.find().forEach(function (fileObj) {
var readStream = fileObj.createReadStream('images');
var writeStream = fileObj.createWriteStream('s3images');
readStream.pipe(writeStream);
});
}
Hopefully after this you will now see your new store's file sizes matches the old one!
3) Optionally, remove the old store. If you keep both, inserted files are added to both, with priority given to the first store in the array.
Reference: https://github.com/CollectionFS/Meteor-CollectionFS/issues/747
I write Sass and use grunt-pleeease to inline #includes etc.
Unfortunately pleeease inlines its source map and ignores the existing one.
The source map file from sass is in the same folder as the css I pass to pleeease (main.css and main.css.map)
Is there a way to tell pleeease to use the existing source map and extend it?
I've also run into this problem. Currently, the pleeease grunt task doesn't write out the external source map even if you select the correct options. You can edit the task to make it do this anyway. I've submitted a pull request to the project on GitHub for this fix.
Note that I still had to specify the in and out options (pleeease gets the location of the original source map from the css file's sourcemap comment; you can specify this manually also using the prev option for sourcemaps, just note that you have to set that option to the contents of the sourcemap file, not the path of the sourcemap file--grunt.file.read() will be of use there):
pleeease: {
dist: {
options: {
in: 'build/styles/styles.css',
out: 'public/styles/styles.min.css',
sourcemaps: {
map: {
inline: false,
sourcesContent: true
}
}
},
files: {
'public/styles/styles.min.css': 'build/styles/styles.css'
}
}
},
Until this fix is implemented into the master branch and published on NPM, you can use the GitHub address of my pull request branch in your package.json to get the fix (please note that I will eventually remove this branch if my pull request is accepted or the fix is achieved in some other way):
"grunt-pleeease": "zeorin/grunt-pleeease#sourcemap-external",
I'm trying to use grunt-contrib-livereload, but can't seem to figure it out. The readme seems to skip over everything that I need explained, and then ends with an example that doesn't work when I try it and doesn't seem directly related to the documentation. I have searched for a better explanation in a blog post or tutorial or whatever, but haven't been able to find one. Can someone please explain how to get started with this tool?
Here are the kinds of questions I have, based on the readme:
The documentation says the livereload task "must be passed the list of files that have changed" --- but how do I pass it this list of files? The example does not seem to illustrate this. Does regarde pass the list?
Is grunt-contrib-connect required? What does it do, and how do I use it? Do I need to learn connect before I try using livereload?
The readme mentions middleware that "must be the first one inserted" --- but inserted into what, before what else? And how is it inserted?
And I suppose I don't understand how I need to manipulate ports. "All the browsers listening on the livereload port will be reloaded" --- but how do I know which browser is listening to which port? Do I need to learn all about ports before I can try using livereload? (Any suggestion on how to best learn about that?)
Finally, in the example, there is a folderMount function that doesn't seem related to any of the documentation before. What is that, and do I need it?
I guess I'm asking if someone can please:
point me towards a tutorial that is much more effective than the current readme;
explain these unexplained parts of the readme, if those answers are what I need to understand the plugin;
or provide a functional example with some explanation of why it is functional.
Live reloading is now built into grunt-contrib-watch version 0.4.0. grunt-contrib-livereload and grunt-regarde will be deprecated soon.
Now just set the option livereload to true in your config and it will create a live reload server then reload after the tasks have run:
grunt.initConfig({
watch: {
all: {
options: { livereload: true },
files: ['lib/*.js'],
tasks: ['jshint'],
},
},
});
By default the live reload server will be started on port 35729. So to enable live reloading on your page just add <script src="http://localhost:35729/livereload.js"></script> to your page.
View more info on the docs: https://github.com/gruntjs/grunt-contrib-watch#live-reloading
Edit: Check versioning info. grunt-contrib-watch now has livereload support baked in.
What a doozy. I ran into issues with this one too so let me do what I can to explain (or at least get you up and running). Keep in mind, this is how I have it set up and it seems to work most of the time.
For starters, you'll want to make sure you've udpated your package.json with the right dependencies. I'm not sure that livereload works with the baked in "watch" task and I've been using grunt-regarde of late. My package.json usually looks like this:
"dependencies": {
"grunt": "~0.4.x",
"grunt-contrib-livereload": "0.1.2",
"grunt-contrib-connect": "0.2.0",
"grunt-regarde": "0.1.1"
},
Obvi you want grunt (duhhh), livereload, connect seems to help with mounting folders, and regarde is like grunt-watch, it just seems to work better (I forget why exactly).
You could make your package.json even better by specifying livereload in its own "devDependencies" object if you're so inclined. Now, run your good old fasioned npm install to get the goodies in your project.
Let's talk gruntfiles:
As you probably know, the gruntfile is what makes the magic happen. Somewhere towards the bottom of your gruntfile, you'll want to specify
grunt.loadNpmTasks('grunt-regarde');
grunt.loadNpmTasks('grunt-contrib-livereload');
grunt.loadNpmTasks('grunt-contrib-connect');
At the top of your gruntfile, we'll want to add some utils for livereload. Under /*global module:false*/, go ahead and add var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;.
After that, you don't really need to learn connect, you just gotta use it. Check my style:
var folderMount = function folderMount(connect, point) {
return connect.static(path.resolve(point));
};
This comes before module.exports = function(grunt) {
Now let's get into the meat of the gruntfile. Again, I forget what connect is doing but this is where the middleware magic comes into play. In your modules.exports, add:
connect: {
livereload: {
options: {
port: 9999,
middleware: function(connect, options) {
return [lrSnippet, folderMount(connect, '.')]
}
}
}
},
Now we want to have the files watched. I like to set up a few different tasks since I don't want my whole grunt process running every time I save a CSS file. Here's what I work with (again, add to module.exports):
regarde: {
txt: {
files: ['styles/*.css', 'index.html'],
tasks: ['livereload']
},
styles: {
files: ['sass/*.scss', 'sass/*/*.scss'],
tasks: ['compass']
},
templates: {
files: ['templates/*.jade'],
tasks: ['jade']
}
},
You can see that I only want livereload to fire when there have been changes to my compiled css (*.css) or to my compiled html. If I edit a SCSS file, I want to fire off just compass. If I edit a jade template, I want to only fire the jade to HTML compiler. I think you can see what's going on. You can toy with this, just be smart about it because you could get caught in an infinite loop.
Lastly, you need to fire off these processes. I like tying them all to my main grunt task because my gruntfile is just that sweet.
// Default task.
grunt.registerTask('default', ['livereload-start', 'connect', 'regarde']);
Now, when you fire up grunt in the CLI, you should (hopefully, maybe, cross your fingers) get something like this:
Running "connect:livereload" (connect) task
Starting connect web server on localhost:9999.
Browse to http://localhost:9999/yourpage.html and watch magic happen.
full gruntfile here. full package.json here.
Here is a solution based on Gulp instead of Grunt and the following Gulpfile.js to get livereload working:
var gulp = require('gulp');
var connect = require('connect');
var connectLivereload = require('connect-livereload');
var opn = require('opn');
var gulpLivereload = require('gulp-livereload');
var config = {
rootDir: __dirname,
servingPort: 8080,
// the files you want to watch for changes for live reload
filesToWatch: ['*.{html,css,js}', '!Gulpfile.js']
}
// The default task - called when you run `gulp` from CLI
gulp.task('default', ['watch', 'serve']);
gulp.task('watch', ['connect'], function () {
gulpLivereload.listen();
gulp.watch(config.filesToWatch, function(file) {
gulp.src(file.path)
.pipe(gulpLivereload());
});
});
gulp.task('serve', ['connect'], function () {
return opn('http://localhost:' + config.servingPort);
});
gulp.task('connect', function(){
return connect()
.use(connectLivereload())
.use(connect.static(config.rootDir))
.listen(config.servingPort);
});
I know this is a little old but can help someone.
In the Gruntfile.js add "options":
sass: {
files: 'scss/**/*.scss',
tasks: ['sass'],
options: {
livereload: true,
}
}
In the index add:
<script src="http://localhost:35729/livereload.js"></script>