How to compile project's CSS files into one file - ember.js

By default ember-cli seems to be set up not to compile css files into one (as it does with the JS files).
What is the best way to configure ember-cli to merge all files in app/styles (and subdirectories) into one app.css file (and then fingerprint etc)? Is this possible via the Brocfile or do I need to override EmberApp.styles()?
Update: As far as I can see there are the following (not very elegant) options:
1) Using SASS and #import the CSS files into app.scss individually. The downside of this is that I need to use an extra plugin (SASS) and that SASS does not seem to allow for globbing patterns in #import (e.g. #import('**/*.scss')), which makes this solution cumbersome for big projects.
2) Overriding EmberApp.styles() such that it does not copy the CSS files (this is currently being done by a wrapper around broccoli-static-compiler) and configuring Broccoli such that it concatenates the css files into app.css. This solution seems a bit hacky though and there is a risk of incompatibility with newer versions of ember-cli.
3) Workaround: Use broccoli-funnel and broccoli-concat to do the concatenation yourself.
In Brocfile.js:
var appTree = app.toTree()
var concatenated = concat(appTree, {
inputFiles: [
'**/*.css'
],
outputFile: '/assets/app.css',
});
module.exports = mergeTrees([appTree, concatenated], { overwrite: true });
This will create a new app.css with all our concatenated CSS in /assets/app.css.However, this file not fingerprinted. Our assets directory now looks something like this:
/assets/app.css
/assets/app-<fingerprint>.css
So a - admittedly hacky - second step is to 1) get the filename of the fingerprinted app-<fingerprint>.css, 2) delete app-<fingerprint>.css and 3) rename app.css to app-<fingerprint>.css. This last step can be automated using Grunt or gulp.

Personally, I think SCSS would be the way to go. It is the simplest solution and there are other advantages to using SCSS besides importing things into one file (variables for repeated patterns, for example).
In addition, manually adding files allows the developer to configure exactly where each piece of code is included. I don't see that as a con, but I can understand the other point of view and I've definitely spent 5m trying to figure out why my styles weren't being applied until I realized it was because I didn't include a new style file.
Edit: There are some node-sass globbing solutions available that could probably be added if that is a big show stopper.

Related

Tailwindcss prettier plugin only affects css files

Ive installed the prettier-plugin-tailwindcss in my emberjs app. It runs and sorts the classes in my css files correctly but it doesnt touch the handlebars files. The standard prettier stuff still works in the handlebar files.
Ive tried adding a twConfig to the .prettierrc as suggested in the docs but that was unrecognised.
I'd really like to use this plugin but I need to support the handlebars files. Please let me know if anyone has any ideas on how I could solve this.
Here's my current prettierrc.yaml
# We use pretty much all defaults from Prettier https://prettier.io/docs/en/options.html
# We prefer single quotes to align with our internal RECONZ styleguide
singleQuote: true
twConfig: 'app/tailwind/config.js' // adding this throws this error below
// [warn] Ignored unknown option { twConfig: "app/tailwind/config.js" }.
overrides:
- files: '*.hbs'
options:
parser: 'glimmer'
# The Ember community uses single quotes in JS & double in templates
singleQuote: false
These are the versions I have installed:
"prettier": "^2.6.0",
"prettier-plugin-tailwindcss": "^0.1.11",
yarn: v1.22.17
UPDATE: the issue seems to be the parser which is set to glimmer When I tried with html instead the plugin worked but unfortunately I need to keep the parser as glimmer because html also causes some unwanted effects. Is there another option I could use?

Integrate SASS/SCSS on Ember Project with POD structure

I just want to ask what is the best approach to integrate sass/scss on ember project?
Currently my project is in pod structure and I just import style.scss on main app.scss under styles folder.
Is it fine or there is a better approach?
--- app
---- pods
------- home
---------- template.hbs
---------- controller.js
---------- style.scss
---- styles
------- app.scss
Then in app.scss styles imported look like this
#import "./app/pods/home/style.scss";
I haven't used pods in years - because (like expecting controllers to be removed) - I was told that there was going to be a new file layout system. Since hearing that / I've heard bits and pieces of conversation that lead me to believe that pods aren't really a go-to for new projects.
That being said, I share your desire to have a nice file structure. I'd love to 'drag' a folder from one project to another / and just have all the parts of the component copy over.
Since we have the app.scss - (you said you're using sass) - / that kinda acts as the index.
I include resets and mixins and a bunch of stuff for setup. - so, that's not really podish... and maybe there are 'page' level kinda layout... which doesn't really fit either... - so, what it comes down to is really 'components', right?
ember-component-css is pretty cool - but it also has some opinions that could clash.
There's this - https://github.com/justtal/ember-cli-sass-pods - but it's 4 years old / (but so are pods) - so, it might still work great.
Because there isn't a really clear path here... I just create a component folder in styles/components/component-name.styl - and then in my styles/components.styl I #import 'component-name.styl - and then in my app.styl I import the components...
In my case / I actually like to use the cascade - and I need the files to all to be combined - in order. I can't have some of it in the vendor file.
It's not ideal (just because I have to create each file explicitly and register it) - but I can't afford to just keep wishing there was a better file layout.
Instead of fuzzy searching component-name > template
I just search template > component-name
¯\_(ツ)_/¯
I wonder which style will cause me less pain in future transitions. They'll offer codemods to help / but they can't account for unique configurations.
I'd suggest asking this in the official discuss forum. You'll get the real answers there. : )
https://discuss.emberjs.com/
app/styles directory, is the home for stylesheets like CSS, SASS, or LESS.
Folders like vendor and public that can also hold many other files of the developer's choice.
So in your case if you wish to have separate scss file for each pod,
you can put it in the place as you mentioned. (else)
have it under app/styles/pod1.scss and import it under .ember-cli-build.js -> app.import('app/styles/pod1.scss')
[References]
You can get the detailed view of Project layouts, Stylesheet compilation, Assets and dependencies below
Project layouts
Stylesheet compilation
Assets and dependencies
Besides ember-component-css there is ember-css-modules.
Both addons try to achieve about the same goal, however I really prefer ember-css-modules.
That addon has an addon called ember-css-modules-sass. Both together will easily allow you to write one sass file per component.
You just place a styles.scss file in your component pod (app/components/my-component/styles.scss and then use local-class="my-class" instead of class="my-class" in your template.
Your classes in your scss will be automatically namespaces.

Referencing asset in javascript

The Ember CLI guide describes how assets can be referenced in the templates and the CSS - but what is the proper way of referencing an asset (say an image) from my javascript code?
Specifically I am concerned about the asset path getting fingerprinted correctly when building assets for production. It seems like ember-cli is using broccoli-asset-rev for this, but according to its documentation, only <script> tags in the HTML and url() in CSS will be fingerprinted. Is there any way (probably through another broccoli plugin) to get asset paths in the .js files fingerprinted, too?
I placed an image called car.jpeg under public/assets/images and then was able to reference it in my application.js route file as assets/images/car.jpeg
Works great
UPDATE
One picture is worth a thousand words... :)
I found the issue. This works out of the box as expected - it turned out that my asset (image) was not in the right location, so occurrences of it's path in the JS files never got replaced with the fingerprinted version.

sprockets - precompiling a standalone asset

I am trying to make sprokets compile a single standalone js asset, so it will uglify and minify it and be part of the entire rails projects.
I need that this js to have a non-digest name, so it's will not change (i.e. embedded in other websites, etc)
I can't seem to force rails (4) /sprockets to do my bidding.
What I tried:
Adding the asset (script.js) in a misc folder unders assets/javascripts and not load it in the sprockets javascript manifest. While this keeps it in the project, it doesn't get uglified and minified, and doesn't get automatically loaded via asset-sync.
Tried adding another manifest called scripts-manifest.js to //= require script.js asset, to add its path in the precompile path in application.rb, but the problem is that rails 4 adds digest to all assets no matter what (doesn't work like that in rails 3)
Tried using https://github.com/alexspeller/non-stupid-digest-assets to add a non digest version of the asset. I may have done it incorrectly, as it doesn't work or do anything..
I add the initializer NonStupidDigestAssets.whitelist = ["script.js"] and tried putting it in app/assets/javascripts/misc and in public/ but it still won't work/
I have read that this gem should help in most cases, and I am sure I am doing something wrong with either path definition or no including it somewhere
One way to do this is to add an initializer that generates the compiled versions directly.
Add your js file to a subfolder in /app/assets/javascripts. Don't include this in application.js so it isn't added to the compiled assets.
Create an initializer in /config/initializers that uses uglify directly
output_file = "#{Rails.root}/public/public_script.js"
input_file = "#{Rails.root}/app/assets/javascripts/non_digest/public_script.js"
uglified = Uglifier.compile(File.read(input_file))
File.open(output_file, 'w') {|f| f.write(uglified) }
Include the public js file (in this example: /public/public_script.js) in your application layout
This way you have direct access to make custom changes to how uglify handles your js and the location of the file never changes for your external services accessing them.
I did all this locally and tested that it worked using the beta version of Rails 4.2
Just wanted to add my own solution based off Ken's answer.
I created non_digest.rb in config/initializers:
Dir["#{Rails.root}/app/assets/javascripts/non_digest/*"].each do |asset|
asset_name = File.basename(asset)
asset_output = "#{Rails.root}/public/external/#{asset_name}"
asset_uglified = Uglifier.compile(File.read(asset))
File.open(asset_output, 'w') {|a| a.write(asset_uglified) }
end
Don't forget to stub the file in javascripts/application.js. as we probably don't want it compiled with the rest of our JS and we can continue to use //= require_tree .:
//= stub non_digest/external_bookmarklet
the way you would do this with rails 4 is the following:
add it to the precompile list config.assets.precompile += %w(your_file_name.js)
make sure it's not referenced in application.js (directly or via require_tree)
symlink the digested file on deployment
read the manifest.yml to get the actual filename
ln -s digested-filename.js actual-filename.js
since rails 4, generation of non-digested assets has been removed (for good reasons) and this is a simple and straight forward way to implement the desired behavior.

where to place the js_plugins and css_plugins?

where to place the js_plugins and css_plugins?
I want to create a html/css template.some css files and are coded myself,such as
css/my.css
js/site.js
but sometimes I want to use some existed css or js plugins from other people who had shared on web,such as
1.some plugins only have css,no js needed. (ex:css3_button.css)
2.some plugins have both css and js. (ex:jquery.prettyphoto.js && jquery.prettyphoto.css)
for these plugins ,where should i put them in my template folder?
i do it like this bellow, but i don't think my structure is good enough.
index.html
css
....my.css
js
....my.js
css_plugin
....css3_button
........css3_button.css
js_plugin
....jquery_prettyphoto
........jquery.prettyphoto.css
........jquery.prettyphoto.js
how to place these files, to ensure the easy managing in the feature?
I use static folder, which includes folders for CSS, images and JavaScript. You can also add a folder for your plugins, where each plugin will be in its own folder.
You can replicate your general structure inside each plugin folder, but most plugins come pre-organized, and changing their structure is not always easy.
example
index.html
static
...js
...css
...img
...plugins
......myFavoritePlugin
.........css
.........js
.........img
......myFavoritePlugin2
.........css
.........js
.........img
Keeping the plugin files together makes their maintenance easier, but it affects performance. It is best practice to combine CSS and JavaScript files when deploying on production machines. You can have best of both worlds if you use build scripts, such as ant