I have a Vite 4 project that uses vanilla JS & no frameworks. When I reference an asset using CSS url(), it throws a 404 error. The path works fine in HTML img src. I saw the answer for Vue but don't know how it applies to my project without a framework. Merely importing an asset from the index.js file changes nothing.
_search-input.scss
.search-input {
width: 100%;
background-image: url("../../assets/icons/search.svg");
}
Index.js:
import "./styles/index.scss"
console.log("index file")
Project structure:
├── src/
│ ├── assets/
│ │ └── icons/
│ │ └── search.svg
│ ├── styles/
│ │ ├── components/
│ │ │ └── _search-input.scss
│ │ └── index.scss
│ └── index.js
└── index.html
I removed a single ../ from the path and now the image loads. However, isn't ../assets/icons/search.svg an invalid path? From search-input.scss I'm supposed to go up two levels to get to src/ and then reach assets. My IDE also complains that this path can't be resolved. Why does this work? What is this path relative to?
CSS url() paths are relative to the current css location, in contrast to HTML img src which is not relative to the current path.
Maybe try to add another ../ to your css path.
For example, let's say we have the following "clean architecture" project structure:
.
│ README.md
│ package.json
│ ...
│
└─── src
│ │ app.js
│ │ app.test.js
│ │ ...
│ │
│ └─── entities
│ │ │ foo.js
│ │ │ foo.test.js
│ │ │ bar.js
│ │ │ ...
│ │
│ └─── useCases
│ │ │ useFooAndBarToBaz.js
│ │ │ ...
│ │
...
How could a test be written to enforce the architectural concept that Entities should not have outward dependencies? IE: no file in the /entities directory should import and use any classes, functions etc found in another directory (/useCases directory in this example).
If possible, I would like to use Jest to write the test(s) (ideally in app.test.js to test the whole /entities directory, but if that's not possible then in foo.test.js to test the content of foo.js, etc etc), but I don't see anything glaringly obvious in the Jest docs about testing file imports.
There may be alternative ways to go about this (can Jest be used in combination with a bash script to walk the directories or something?), so I'm open to ideas.
Premise
Let's say I have two different AMD-based AngularJS apps, each of them with their own sets of controllers, directives, services, etc. Each of them are bundled in their own dist/{app-name}.min.js and loaded in <script> tags in the same HTML page (this is all in the context of a CMS that then contains these apps among other things)
Now the apps end up sharing some of the services, directives, and vendor libraries like angular itself, moment, jQuery, etc, so I've made another folder for all of these resources, which results in a bundle that will be added to the page before the js bundles of the apps:
<script src="/some-path/dist/shared-resources.min.js"></script>
<script src="/some-path/dist/first-app.min.js"></script>
<script src="/some-path/dist/second-app.min.js"></script>
This is the resulting folder structure:
.
├── shared-resources/
│ ├── dist/
│ ├── src/
│ │ └── common/
│ │ ├── directives/
│ │ ├── modules/
│ │ ├── services/
│ │ └── vendor/
│ └── build.js
│
├── first-app
│ ├── dist/
│ ├── src/
│ │ ├── first-app/
│ │ │ ├── controllers/
│ │ │ ├── modules/
│ │ │ ├── services/
│ │ │ ├── directives/
│ │ │ └── app.js
│ │ └── first-app.js
│ └── build.js
│
└── second-app
├── dist/
├── src/
│ ├── second-app/
│ │ ├── controllers/
│ │ ├── modules/
│ │ ├── services/
│ │ ├── vendor/
│ │ └── app.js
│ └── second-app.js
└── build.js
This is an example of what the build.js file for the common modules looks like
({
baseUrl: 'src',
removeCombined: true,
out: 'dist/shared-resources.min.js',
paths: { // forcing a `common/{modulename}` convention
'common/jquery': 'common/vendor/jquery.min',
'common/moment': 'common/vendor/moment.min',
'common/angular': 'common/vendor/angular/angular.min',
},
shim: {
'common/angular': {
exports: 'angular',
}
},
include: [
'common/modules/vendors', // Just a bundle of every vendor modules
'common/directives/common-directive',
'common/services/common-service'
],
})
Now my intention was to have all the shared modules being namespaced with common/, so each of the apps could require common/angular, common/directives/common-directive, and so on, and then exclude the common path when creating their bundle (since all the common modules are already present in the shared-resources.js bundle), for example:
// first-app/src/first-app/controllers/app-controller.js
define([
'first-app/modules/controllers',
'first-app/services/app-service',
'common/services/common-service'
], function (controllers) {
'use strict';
controllers.controller('AppController', ['CommonService', 'AppService', function (CommonService, AppService) {
CommonService.call();
AppService.call();
}]);
});
// first-app/build.js
({
baseUrl: 'src',
out: 'dist/first-app.min.js',
paths: {
'common': 'empty:'
},
name: 'first-app',
deps: ['first-app/app']
})
Problem
The problem is how these two apps, which again are both loaded on the page (this can't be avoided), are supposed to correctly look up these common modules.
Given that each of the apps have obviously a different baseUrl, they are put in different RequireJS contexts, otherwise the baseUrl of the second app would override the baseUrl of the first one, causing the incorrect loading of its modules:
// first-app/src/first-app.js
require.config({
context: 'first-app',
baseUrl: 'first-app/src',
})(['fist-app/app']);
// first-app/src/second-app.js
require.config({
context: 'second-app',
baseUrl: 'second-app/src',
})(['second-app/app']);
But putting them in context then causes the look up for the common modules to fail, as the modules are looked in the baseUrl of the context. Actually this happens only for the second app (second in order of loading), while the first app to be included in the page can load the common modules fine
Question
So how should I make the apps to correctly share the common modules? Am I approaching this wrong? Should I use something else than RequireJS?
The context feature of RequireJS is really meant to be used to handle a case where you have to load two conflicting applications on the same page and the conflict cannot be resolved otherwise. The way you've written your code so far may have led you to want to have two baseUrl values, but there is nothing in your question that indicates that you must have two baseUrl values. There are ways to avoid it:
Modules that are part of a logical set of modules should load each other with relative paths. For instance, the module you give as example could be:
// first-app/src/first-app/controllers/app-controller.js
define([
'../modules/controllers',
'../services/app-service',
'common/services/common-service'
], function (controllers) {
paths can be set to make it look like a module is directly under baseUrl even if it is not. You could have:
paths: {
'first-app': 'first-app/src'
'second-app': 'second-app/src'
}
and yes, loading first-app/app will work. RequireJS will transform the path to first-app/src/app.js.
I'm trying to watch my app's js files and dependencies's css & js files for link them in my index.html file.
I'm using grunt-contrib-watch for the job, but it seems that it doesn't work as I expected. There are directories in the file system tree that doesn't trigger the watch task.
this is my grunt watch config:
watch: {
vendors: {
files: ['www/vendors/**/*.js', 'www/vendors/**/*.css'],
tasks: ['wiredep']
},
app: {
files: ['www/app/**/*.js', 'www/app/**/*.css', 'www/css/**/*.css'],
tasks: ['tags']
}
}
this is my folders structure:
C:.
└───www
├───app
│ └───modules
│ └───main
│ └───controllers
├───css
├───images
└───vendors
├───angular
├───bootstrap
│ ├───dist
│ │ ├───css
│ │ ├───fonts
│ │ └───js
│ ├───fonts
│ ├───grunt
│ ├───js
│ └───less
└───jquery
├───dist
└───src
├─── ...
Here is the PROBLEM. When I add/delete a js or css file to a directory that already have js/css file, the watcher task triggers and it works. But any other folder that doesn't have js/css placed in (and the folder is placed in vendors or app folders), doesn't trigger the watcher, and the task won't run.
Why is that? and how can I solve it? I want the watcher to work on any level in the directory's tree.
I'm using grunt 0.4.5, and grunt-contrib-watch version 0.6.1.
After installing BackboneJS, jQuery etc I have a very large bower_components directory.
├───.idea
│ ├───runConfigurations
│ └───scopes
└───app
├───bower_components
│ ├───backbone
│ ├───jquery
│ │ ├───dist
│ │ └───src
│ │ ├───ajax
│ │ │ └───var
│ │ ├───attributes
│ │ ├───core
│ │ │ └───var
│ │ ├───css
│ │ │ └───var
│ │ ├───data
│ │ │ └───var
│ │ ├───effects
│ │ ├───event
│ │ ├───exports
│ │ ├───manipulation
│ │ │ └───var
│ │ ├───queue
│ │ ├───sizzle
│ │ │ ├───dist
│ │ │ └───test
│ │ │ ├───data
│ │ │ └───unit
│ │ ├───traversing
│ │ │ └───var
│ │ └───var
│ └───underscore
├───css
└───js
What is best practice to reference these? e.g directly, Grunt task to copy bits to the main app, or put the bower_componects inside the ~/app directory?
Don't copy them over to your app - that completely defies the intent of a package manager like Bower! By doing so, you'd take control over these files away from your package manager - and then you're left in the same state as before, manually having to copy over files every time with an update of these dependencies.
Just reference the files inside the bower_components/ directory directly (in your HTML, most likely). If you don't like that location or name, you can have bower put your components some place else, see .bowerrc doc: http://bower.io/docs/config/
I can think of a use for only using specific files from your bower_components directory - but only at build time:
If you write a grunt task that runs only at deploy time and strips away all unused files from the bower_components directory, that of course makes sense and does not go against the idea of a package manager, because it only happens on each deploy, a point when the package manager has no responsibilities.
The only problem you might get with this approach is if you have it end up copying files over to a different directory - because then you'd have to change the references to all files from bower_components before deploying, too. The easy solution is to not duplicate files, but instead, only delete the ones you don't need.
Just leave them in bower_components and refer proper files inside your index.html file. You can do this manually, or use tools like grunt wiredep to do this for you automatically.