I've tried several different solutions but not a single one have worked for me.
I'm using.NET Core, latest Aurelia/Aurelia CLI and Font-Awesome installed using npm install font-awesome --save.
Solution 1:
New file: prepare-font-awesome.js in folder \aurelia_project\tasks
import gulp from 'gulp';
import merge from 'merge-stream';
import changedInPlace from 'gulp-changed-in-place';
import project from '../aurelia.json';
export default function prepareFontAwesome() {
const source = 'node_modules/font-awesome';
const taskCss = gulp.src(`${source}/css/font-awesome.min.css`)
.pipe(changedInPlace({ firstPass: true }))
.pipe(gulp.dest(`${project.platform.output}/css`));
const taskFonts = gulp.src(`${source}/fonts/*`)
.pipe(changedInPlace({ firstPass: true }))
.pipe(gulp.dest(`${project.platform.output}/fonts`));
return merge(taskCss, taskFonts);
}
Updated build.js\aurelia_project\tasks
import prepareFontAwesome from './prepare-font-awesome'; // Our custom task
export default gulp.series(
readProjectConfiguration,
gulp.parallel(
transpile,
processMarkup,
processCSS,
prepareFontAwesome // Our custom task
),
writeBundles
);
Included font-awesome in html
<link rel="stylesheet" href="scripts/css/font-awesome.min.css">
Error:
GET http://localhost:9000/scripts/css/font-awesome.min.css
Solution 2:
Updated aurelia.json
{
"name": "font-awesome",
"path": "../node_modules/font-awesome/",
"main": "",
"resources": [
"css/font-awesome.min.css"
]
}
Added font files in root/font-awesome/fonts
Included font-awesome in html
<require from="font-awesome/css/font-awesome.min.css"></require>
Error: No error but icons are not shown
Solution 3:
Updated build.js:
import gulp from 'gulp';
import transpile from './transpile';
import processMarkup from './process-markup';
import processCSS from './process-css';
import { build } from 'aurelia-cli';
import project from '../aurelia.json';
import fs from 'fs';
import readline from 'readline';
import os from 'os';
export default gulp.series(
copyAdditionalResources,
readProjectConfiguration,
gulp.parallel(
transpile,
processMarkup,
processCSS
),
writeBundles
);
function copyAdditionalResources(done){
readGitIgnore();
done();
}
function readGitIgnore() {
let lineReader = readline.createInterface({
input: fs.createReadStream('./.gitignore')
});
let gitignore = [];
lineReader.on('line', (line) => {
gitignore.push(line);
});
lineReader.on('close', (err) => {
copyFiles(gitignore);
})
}
function copyFiles(gitignore) {
let stream,
bundle = project.build.bundles.find(function (bundle) {
return bundle.name === "vendor-bundle.js";
});
// iterate over all dependencies specified in aurelia.json
for (let i = 0; i < bundle.dependencies.length; i++) {
let dependency = bundle.dependencies[i];
let collectedResources = [];
if (dependency.path && dependency.resources) {
// run over resources array of each dependency
for (let n = 0; n < dependency.resources.length; n++) {
let resource = dependency.resources[n];
let ext = resource.substr(resource.lastIndexOf('.') + 1);
// only copy resources that are not managed by aurelia-cli
if (ext !== 'js' && ext != 'css' && ext != 'html' && ext !== 'less' && ext != 'scss') {
collectedResources.push(resource);
dependency.resources.splice(n, 1);
n--;
}
}
if (collectedResources.length) {
if (gitignore.indexOf(dependency.name)< 0) {
console.log('Adding line to .gitignore:', dependency.name);
fs.appendFile('./.gitignore', os.EOL + dependency.name, (err) => { if (err) { console.log(err) } });
}
for (let m = 0; m < collectedResources.length; m++) {
let currentResource = collectedResources[m];
if (currentResource.charAt(0) != '/') {
currentResource = '/' + currentResource;
}
let path = dependency.path.replace("../", "./");
let sourceFile = path + currentResource;
let destPath = './' + dependency.name + currentResource.slice(0, currentResource.lastIndexOf('/'));
console.log('Copying resource', sourceFile, 'to', destPath);
// copy files
gulp.src(sourceFile)
.pipe(gulp.dest(destPath));
}
}
}
}
}
function readProjectConfiguration() {
return build.src(project);
}
function writeBundles() {
return build.dest();
}
Updated aurelia.json
{
"name": "font-awesome",
"main":"",
"path": "../node_modules/font-awesome",
"resources": [
"css/font-awesome.css",
"/fonts/fontawesome-webfont.woff2",
"/fonts/FontAwesome.otf",
"/fonts/fontawesome-webfont.eot",
"/fonts/fontawesome-webfont.svg",
"/fonts/fontawesome-webfont.ttf"
]
}
Included font-awesome in html
<require from="font-awesome/css/font-awesome.css"></require>
Error:
get:
http://localhost:9000/font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0
(same with woff and ttf)
It's really strange because the files are copied and the url is correct..
Folder structure:
Tested a couple of different sources
What am I missing?
I would prefer a less implementation so I can import Font-Awesome in my master less file.
Based off of the discussion, since you are hosting your project inside the wwwroot folder, you must base your "gets" for files from there.
So, if you move your font files into wwwroot/fonts/font-name.woff (or somewhere thereabouts), you should be golden.
If you are on a webpack based project generated with latest (2019ish) aurelia cli , then adding fontawesome or bootstrap is pretty simple.
step 1: install fontawesome
check the official docs here. Just for completeness, here is the npm or yarn way for free version
//with npm
npm install --save-dev #fortawesome/fontawesome-free
// yarn
yarn add --dev #fortawesome/fontawesome-free
step 2: import the font
in your main.js or main.ts or app.js or app.ts , all of them will work equally well, which is better? ask google.
import '#fortawesome/fontawesome-free/css/all.min.css';
And an even simpler method would be to add the CDN version into the head of your index.esj or index.html file
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.1/css/all.css" />
all of the above work equally well, personally for public apps, I prefer CDN solution due to browser cache.
Related
I have simple vue3 app. It run well with npm run dev but when I try, as described in the official documentation, npm run build to ship it to production, I got the error below:
$ npm run build
> salaty#0.0.0 build
> vue-tsc --noEmit && vite build
src/main.ts:2:17 - error TS7016: Could not find a declaration file for module './Salaty.vue'. '/home/path/to/Salaty/src/Salaty.vue.js' implicitly has an 'any' type.
2 import App from './Salaty.vue'
~~~~~~~~~~~~~~
Found 1 error.
This src/main.ts :
import { createApp } from 'vue'
import App from './Salaty.vue'
createApp(App).mount('#app')
The application run well in dev. I don't know what is the problem?! I don't think I have to rename files manually before build, do it?!
Update:
Salaty.vue src:
<script>
/*let baseUrl = 'https://api.pray.zone/v2/times/today.json';
let city = 'kafr-saqr';
let timeformat = 1;
let school = 5;*/
import config from './config.json';
import moment from 'moment'
import LoadingComp from './components/LoadingComp.vue';
import Clock from './components/Clock.vue'
export default{
data(){
return {
dataRes: null,
times: null,
now: moment(),
nextTime: null,
error: null,
day: 'today.json'
}
},
computed: {
fetchUrl(){
console.log(config.baseUrl+this.day+'?city='+config.city+'&timeformat='+config.timeformat+'&school='+config.school)
return config.baseUrl+this.day+'?city='+config.city+'&timeformat='+config.timeformat+'&school='+config.school;
},
},
methods: {
async fetchData(){
this.dataRes = null;
try{
const res = await fetch(this.fetchUrl);
this.dataRes = await res.json();
}
catch(error){
this.error= 'Error! Could not reach the API.\n' + error;
alert(this.error)
}
},
},
mounted(){
this.fetchData();
localStorage.setItem("city",config.city);
},
components:{
LoadingComp,Clock
},
watch:{
dataRes(){
if (!this.dataRes) return null;
const cTimes = config.filteredTimes.reduce((obj, key)=>({ ...obj, [key]: this.dataRes.results.datetime[0].times[key] }),{});
for (const t in cTimes){
cTimes[t]=moment(this.dataRes.results.datetime[0].date.gregorian+' '+cTimes[t]);
//console.log(cTimes[t].unix(), this.nextTime, t, typeof(this.nextTime))
if (cTimes[t].unix() > this.now.unix() && this.nextTime == null){
this.nextTime = cTimes[t];
// console.log("YYYYY> ", cTimes[t],t)
cTimes[t].next = true;
}
}
if (this.nextTime == null){
this.day = 'tomorrow.json';
}
this.times = cTimes;
},
day(){
this.fetchData();
},
/*nextTime(){
this.nextTime == null
this.fetchData();
}*/
},
};
</script>
<template>
<Clock #response="(p) => {if(p > this.nextTime) this.fetchData()}" :nextTime="this.nextTime" />
{{ dataRes? dataRes.results.location.city:''}}
<ul v-if="times">
<li v-for="(time,k,i) in times">{{k}} > {{time.format('hh:mm a')}} <strong v-if="time.next">* Upcoming</strong></li>
</ul>
{{times? times.Fajr:''}}
<div v-if="!dataRes && error == null"><LoadingComp /></div>
<pre v-if="dataRes">{{dataRes}}</pre>
</template>
I'd like to add the current module folder during my webpack compilation to my dist/ directory. For now, in /dist, I have something like that
const toCopy = [
'./../../../../node_modules/flatpickr/dist/flatpickr.min.js',
'./../../../../node_modules/flatpickr/dist/flatpickr.min.css',
]
this is the part of my webpack CopyPlugin
...
plugins: [
new CopyPlugin({
patterns: toCopy.map((entry) => {
console.log(entry);
return { from: entry }
})
})
]
And it gives me that
/dist
flatpickr.min.css
flatpickr.min.css
And I'd like that in order to avoid conflict if files from different modules have the same name .
for example, flatpickr as a ie.css, fr.js... but some other module could also have those files
/dist
/flatpickr
flatpickr.min.css
flatpickr.min.css
I've ended by created a loop over all my assets to copy to keep the CopyPlugin structure
const toCopy = new Map();
toCopy.set('popper', './../../contrib/bootstrap_sass/js/popper.min.js',);
toCopy.set('flatpickr', ['./../../../../node_modules/flatpickr/dist/flatpickr.min.js',
'./../../../../node_modules/flatpickr/dist/flatpickr.min.css']);
let toCopyFormatted = [];
for (let [dest, entries] of toCopy.entries()) {
if (typeof entries === 'string') {
let data = {to: dest}
data['from'] = entries;
toCopyFormatted.push(data);
} else {
entries.forEach(function (v, k) {
let data = {to: dest}
data['from'] = v;
toCopyFormatted.push(data);
})
}
}
Generally, is there a way to customize the app code during build step?
Specifically, there is the typical need to make requests from the application to the local backend ([1], [2], [3], [4]).
localhost doesn't work since the server and the app are on different hosts (when using Android emulator or an actual physical device).
The actual IP address of the host in the same network works but in a multi-developer project it's a hassle for everyone to constantly change the constant IP in the code to that of their development machine.
With Webpack a case like that could be solved with DefinePlugin replacing a placeholder with the IP address of the machine the build is happening on.
We ended up using somewhat hacky approach inspired by transformers like react-native-typescript-transformer or react-native-sass-transformer. It's idea is pretty much equivalent to the mentioned DefinePlugin of Webpack.
First, some transformer files in the project directory (you can name them however you like, just update the references):
configBuildReplacements.js
// whatever logic you need
module.exports = {
API_HOST_PLACEHOLDER: `http://${getLocalNetworkAddress()}:3000`,
SOME_OTHER_DYNAMIC_VALUE: someFun(),
}
configBuildReplaceTransformer.js
const semver = require('semver')
let upstreamTransformer = null
const reactNativeVersionString = require('react-native/package.json').version
const reactNativeMinorVersion = semver(reactNativeVersionString).minor
if (reactNativeMinorVersion >= 56) {
upstreamTransformer = require('metro/src/reactNativeTransformer')
}
else if (reactNativeMinorVersion >= 52) {
upstreamTransformer = require('metro/src/transformer')
}
else if (reactNativeMinorVersion >= 47) {
upstreamTransformer = require('metro-bundler/src/transformer')
}
else if (reactNativeMinorVersion === 46) {
upstreamTransformer = require('metro-bundler/build/transformer')
}
else {
// handle RN <= 0.45
const oldUpstreamTransformer = require('react-native/packager/transformer')
upstreamTransformer = {
transform({ src, filename, options }) {
return oldUpstreamTransformer.transform(src, filename, options)
},
}
}
module.exports.transform = function (src, filename, options) {
// handle RN >= 0.46
if (typeof src === 'object') {
({ src, filename, options } = src)
}
const replacements = require('./configBuildReplacements')
const modifiedSrc = Object.keys(replacements).reduce(
(src, replacementKey) => src.replace(
new RegExp(replacementKey, 'g'),
replacements[replacementKey],
),
src,
)
return upstreamTransformer.transform({
src: modifiedSrc,
filename,
options,
})
}
The exported transform function uses the exported object from the previous file configBuildReplacements.js as a dictionary to replace key substrings with value substrings in the source code before handing this code to the default (upstream) transformer.
And to connect this new transformer to the project:
with Expo, add the transformer packager option to app.json:
{
"expo": {
"packagerOpts": {
"transformer": "configBuildReplaceTransformer.js"
}
}
}
without Expo, add getTransformModulePath() to rn-cli.config.js (which is the default path to the optional config file for React Native CLI, which is extremely poorly documented at the moment of this writing):
module.exports = {
getTransformModulePath() {
return require.resolve('./configBuildReplaceTransformer')
},
}
After this is done, just like with DefinePlugin, code like
get('API_HOST_PLACEHOLDER/info')
will become something like
get('http://192.168.42.23:3000/info')
How do we organize our test directory when developing some libraries that uses Native js code?
I tried to work this out, but I'm blocked here, with this error at runtime when running test/test.sh:
Elm.Native.Mylib = {};
^
TypeError: Cannot read property 'Native' of undefined
git repository
My directories are structured this way:
Mylib:
- src :
- Mylib.elm
- Native :
- MyLib.js
- tests :
- Test.elm
- Test.sh
- elm-package.json
the tests/elm-package.json contains :
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
,"../src"
],
"exposed-modules": [],
"native-modules": true,
"dependencies": {
"elm-community/elm-test": "1.1.0 <= v < 2.0.0",
"elm-lang/core": "4.0.1 <= v < 5.0.0"
},
"elm-version": "0.17.0 <= v < 0.18.0"
}
the tests/Test.elm is :
module Main exposing (..)
import Basics exposing (..)
import ElmTest exposing (..)
import Mylib exposing (..)
tests : Test
tests =
suite "elm-Mylib Library Tests"
[ ]
main =
runSuite tests
The tests/test.sh is
#!/bin/sh
elm-package install -y
elm-make --yes --output test.js Test.elm
node test.js
The src/Mylib.elm is
module Mylib exposing (..)
import Native.Mylib exposing (..)
import Task exposing (Task)
import Time exposing (Time)
print : a -> Task x ()
print value =
Native.Mylib.log (toString value)
getCurrentTime : Task x Time
getCurrentTime =
Native.Mylib.getCurrentTime
The src/Native/Mylib.js is
Elm.Native.Mylib = {};
Elm.Native.Mylib.make = function(localRuntime) {
localRuntime.Native = localRuntime.Native || {};
localRuntime.Native.Mylib = localRuntime.Native.Mylib || {};
if (localRuntime.Native.Mylib.values)
{
return localRuntime.Native.Mylib.values;
}
var Task = Elm.Native.Task.make(localRuntime);
var Utils = Elm.Native.Utils.make(localRuntime);
function log(string)
{
return Task.asyncFunction(function(callback) {
console.log(string);
return callback(Task.succeed(Utils.Tuple0));
});
}
var getCurrentTime = Task.asyncFunction(function(callback) {
return callback(Task.succeed(Date.now()));
});
return localRuntime.Native.Mylib.values = {
log: log,
getCurrentTime: getCurrentTime
};
};
Try this:
var _user$project$Native_MyLib = function() {
return {
exported: function(arg) { return "One" },
exported2: F2(function(arg) { return "Two" }),
exported3: F3(function(arg) { return "Three" }),
}
}();
It works for grater than Elm 0.17.
Buy you should also use full qualified import:
import Natve.MyLib
exported : String -> String
Native.MyLib.exported
exported2 : String -> String -> String
Native.MyLib.exported2
exported3 : String -> String -> String -> String
Native.MyLib.exported3
User and project values are from your/local elm-package.json:
"repository": "https://github.com/user/project.git",
It seems like this build script is running but the CSS that is output is not minified or auto prefixed. I am attempting to compile SASS, then run the output through Post CSS with Broccoli and the angular-cli. I figure maybe some ember-cli folks could help as well. What am I doing wrong?
The build outputs this in terminal:
Slowest Trees | Total
----------------------------------------------+---------------------
BroccoliTypeScriptCompiler | 1274ms
vendor | 502ms
PostcssFilter | 465ms
but the CSS is the same as if it were output from SASS, not Post CSS.
Here is my angular-cli-build.js:
'use strict';
/* global require, module */
const Angular2App = require('angular-cli/lib/broccoli/angular2-app');
const compileSass = require('broccoli-sass');
const compileCSS = require('broccoli-postcss');
const cssnext = require('postcss-cssnext');
const cssnano = require('cssnano');
const mergeTrees = require('broccoli-merge-trees');
const Funnel = require('broccoli-funnel');
const _ = require('lodash');
const glob = require('glob');
var options = {
plugins: [
{
module: cssnext,
options: {
browsers: ['> 1%'],
warnForDuplicates: false
}
},
{
module: cssnano,
options: {
safe: true,
sourcemap: true
}
}
]
};
module.exports = function(defaults) {
let sourceDir = 'src';
let appTree = new Angular2App(defaults, {
sourceDir: sourceDir,
sassCompiler: {
includePaths: [
'src/style'
]
},
vendorNpmFiles: [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'zone.js/dist/*.js',
'es6-shim/es6-shim.js',
'reflect-metadata/*.js',
'reflect-metadata/*.js.map',
'rxjs/**/*.js',
'#angular/**/*.js',
'rxjs/**/*.js.map',
'#angular/**/*.js.map',
'd3/d3.js',
'three/build/three.js',
'three/examples/js/postprocessing/*.js',
'three/examples/js/shaders/*.js'
]
});
let sass = mergeTrees(_.map(glob.sync('src/**/*.scss'), function(sassFile) {
sassFile = sassFile.replace('src/', '');
return compileSass(['src'], sassFile, sassFile.replace(/.scss$/, '.css'));
}));
let css = compileCSS(sass, options);
return mergeTrees([sass, css, appTree], { overwrite: true });
};
It was the order of operations, my trees were not overwriting appTree!
This works!
return mergeTrees([appTree, sass, css], { overwrite: true });