Is there a better way of importing images in react? - image

I'm importing images into a component, and due to the our file structure a complex relative path is required:
// TODO is there a better way of importing images? image helper?
import browserImg from './../../../assets/images/screenshot-browser.png';
import phoneImg from './../../../assets/images/screenshot-phone.png';
Is there a better way of doing this? Something like the image helper/asset-pipeline in ruby?

If you use Webpack to bundle your application, you can make use of webpack aliases:
resolve: {
alias: {
assets: 'src/assets' // relative to the webpack configuration file
}
}
Then, you can simply use the alias to refer to your assets as such:
import browserImg from 'assets/images/screenshot-browser.png';

Related

How do you include jsm examples with three.js over nodes.js?

I installed three.js using npm install.
I work since month with three.js using the following single import:
import * as THREE from 'three'
Now it is the first time, I am trying to used a jsm example as described on https://threejs.org/docs/#manual/en/introduction/Installation:
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
oc = new OrbitControls();
Now I get the following error:
[SyntaxError: 'import' and 'export' may appear only with 'sourceType: module'] {
It burns down to that the core three.js files import dependencies using
import { LineBasicMaterial } from './LineBasicMaterial.js';
but the jsm files import from three.module.js
import { SaderLib,ShaderMaterial,Vector2} from "../../../build/three.module.js";
So three.module.js is a different script "format"?
I guess, I have to change my gulpfile?
var bundler = watchify(browserify(['./src/index.js'], { debug: true}).transform(babel.configure({presets: ["es2015"]}))) // original
But I admit, that I never really fully understood this part.
Can't believe I am the first one running into this.
How do you include jsm examples with three.js over nodes.js?
Why do the js files under /src use a different include method than under /examples ?

Typescript Type definition for d3 sankey

I have some javascript code which uses d3 sankey plugin for creating a chart. In my new project, I need to reuse the same code, but the new project is in typescript. I am looking for a DefinitelyTyped file for the plugin. I browsed through https://github.com/DefinitelyTyped/DefinitelyTyped, but couldn't find it.
Is there any other location where I can get this file from?
Sankey plugin link: https://github.com/d3/d3-sankey
Also, without a d.ts file for this plugin, is there a way to access it through typescript?
The code in d3 plugin looks something like this:
d3.sankey = function () {
// Rest of the code goes here
}
The way I use it in javascript is as below:
d3.sankey().nodeWidth(30).size([100,100]);
Would appreciate any help or guidance.
Thanks!
As a heads-up, I have just submitted a Pull Request #16051 to DefinitelyTyped which contains TS definitions for d3-sankey.
Once they are merged, they will be published as per standard process to npm/#types. I.e. npm install --save-dev #types/d3-sankey will do.
IMPORTANT: When I wrote them up, I noticed that the current API documentation in the d3-sankey repo appears to be in some need of rectification (e.g. missing methods, mentioning of accessor functions, which are not used in the code base)
When I have a second, I will file an issue there/submit a PR.
UPDATE (2017-05-01):
The "official" TypeScript definitions for d3-sankey are now available (see npm #types/d3-sankey). Simply use them with npm as indicated above.
The PR to update the actual API documentation of d3-sankey to reflect the source code is still awaiting a merge here.
You need to expand the definition of the d3 type to include the sankey() method and the methods it accepts.
At the absolute minimum, you need to extend the d3 module with a declaration file to make clear that d3 has been extended with the d3-sankey module. You do so by creating a definition file that you place within the #types directly with the following contents:
declare module 'd3' {
export function sankey(...args[]) : any;
}
This tells TS that there is a d3 module, and that it exports the function listed. If the d3 module already exists, it extends that module.
So you can then import the d3 service and use it:
import dd3 = require('d3');
dd3.sankey();
If you want to expand on the type file, you instead write the definition file as so:
declare module 'd3' {
interface ISankey {
nodeWidth() : number;
nodeWidth(width : number|{(arg: number) : number}) : void;
// Add Other d3.sankey Methods Here
}
export function sankey() : ISankey;
}

New Scala.js facade for Three.js -> "Cannot find module "THREE""

As https://github.com/antonkulaga/threejs-facade is heavily outdated I tried an approach like: https://github.com/Katrix-/threejs-facade and would like to create a facade for the new three.js library.
I am by no means a JS expert, nor am I a Scala.js expert, so odds are I am doing something really dumb.
After another question I am using this sbt-scalajs-bundler and sbt-web-scalajs-bundler
My build.sbt looks like this:
lazy val client = (project in file("modules/client"))
.enablePlugins(ScalaJSBundlerPlugin, ScalaJSWeb) // ScalaJSBundlerPlugin automatically enables ScalaJSPlugin
.settings(generalSettings: _*)
.settings(
name := "client"
//, scalaJSModuleKind := ModuleKind.CommonJSModule // ScalaJSBundlerPlugin implicitly sets moduleKind to CommonJSModule enables ScalaJSPlugin
,jsDependencies += ProvidedJS / "three.min.js"
)
lazy val server = (project in file("modules/server"))
.enablePlugins(PlayScala, WebScalaJSBundlerPlugin)
.settings(generalSettings: _*)
.settings(
name := "server"
,scalaJSProjects := Seq(client)
,pipelineStages in Assets := Seq(scalaJSPipeline)
//,pipelineStages := Seq(digest, gzip)
,compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value
)
three.min.js is in the resources-folder of my client project.
One part of the Facade is e.g.
#js.native
#JSImport("THREE", "Scene")
class Scene extends Object3D {
and I want to use it like this: val scene = new Scene. On scala.js side this actually compiles just fine, but when I run it I get:
Error: Cannot find module "THREE"
in the browser and I wonder why. It's called like this in three.min.js after all.
Now I tried providing and serving the three.min.js file from the server side as well, because I thought that maybe it was just missing at runtime, but no, that does not seem to be the cause.
So now I wonder what am I doing wrong here?
Just to clarify: Rest of transpiled js works just fine, if I do not export any usage of the Facade!
As explained in this part of Scala.js documentation, #JSImport is interpreted by the compiler as a JavaScript module import.
When you use the CommonJSModule module kind (which is the case when you enable the ScalaJSBundlerPlugin), this import is translated into the following CommonJS import:
var Scene = require("THREE").Scene;
This annotation only tells how your Scala code will be interfaced with the JS world, but it tells nothing about how to resolve the dependency that provides the THREE module.
With scalajs-bundler you can define how to resolve JS dependencies from the NPM registry by adding the following setting to your client project:
npmDependencies += "three" -> "0.84.0"
(And note that you can’t use jsDependencies to resolve these modules with #JSImport)
Also, note that the correct CommonJS import to use three.js is "three" instead of "THREE", so your #JSImport annotation should look like the following:
#JSImport("three", "Scene")
Alternatively, if you don’t want to resolve your dependencies from the NPM registry, you can supply your CommonJS module as a resource file. Just put it under the src/main/resources/Scene.js and refer to it in the #JSImport as follows:
#JSImport("./Scene", "Scene")
You can see a working example here.

vue.js: always load a settings.scss file in every vue style section

I find myself repeating this same pattern in every .vue file, in order to use variables, etc.:
<style lang="scss">
#import "../styles/settings.scss";
.someclass { color: $some-variable; }
</style>
or if it's nested in a folder I have to remember to be careful with the path:
<style lang="scss">
#import "../../styles/settings.scss";
</style>
Is there a way to globally import that settings.scss file in every .vue file I create? I looked in the docs and didn't see it, but maybe I missed it, or maybe this is something I need to leverage webpack to do?
I have struggled with the same question for a while. But there's a really simple fix. This feature comes through node-sass itself.
so you can declare your scss globals in a file, say globals.scss whose path is:
/src/scss/globals.scss
Now you can simply edit the vue-loader config:
loaders: {
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1&data=#import "./src/scss/globals"',
scss: 'vue-style-loader!css-loader!sass-loader?data=#import "./src/scss/globals";'
}
and voila! You have the scss globals available across all your vue components. Hope it helps!
Update:
A lot of settings have been updated in new releases of vue. So the above changes may not seem trvial in latest vue projects. So I'll brief how everything is tied together-
Short version:
Find build/utils.js which would contain a method (most probably named cssLoaders() ). This method would return an object like this :
return {
...
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
...
}
You simply need to change the scss/sass specific line to something like this:
return {
...
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders(['css', 'sass?data=#import "~assets/styles/app";']),
...
}
Long Version:
webpack.base.conf.js contains vue-loader in it, it would look something like this :
...
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
...
The vueLoaderConfig variable is imported from the vue-loader.conf.js file, which is equal to this object:
{
loaders: utils.cssLoaders( Obj ), // actual settings coming from cssLoader method of build/utils.js
transformToRequire: {
//some key value pairs would be here
}
}
in build/utils.js file we find the cssLoaders() method which returns:
....
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
You simply need to update the above code with updated scss configuration like this:
...
{
...
scss: generateLoaders(['css', 'sass?data=#import"~assets/scss/main";']),
...
}
...
Thus, the variables/mixins written in src/assets/scss/main.scss file will be available across all your components.
I reckon you're using webpack?
You can require the settings.scss file in your app.js file something like this
require("!style!css!sass!./file.scss");
hence when it's compiled. All your components will get it. You won't have to require it on each of them.
The official docs have been updated since I asked this question: https://vue-loader.vuejs.org/en/configurations/pre-processors.html
For anyone else viewing this in 2017 and beyond, check out the instructions under 'loading a global settings file'.
If you use the Vue webpack template, you can fix it with one line of code in build/utils.js:
scss: generateLoaders(['css', 'sass?data=#import "~assets/styles/app";'])
Then, in src/assets/styles/app, you add all the #imports and voilà!
For users using Vue CLI, read https://cli.vuejs.org/guide/css.html#css-modules. Example:
// vue.config.js
const fs = require('fs')
module.exports = {
css: {
loaderOptions: {
// pass options to sass-loader
sass: {
// #/ is an alias to src/
// so this assumes you have a file named `src/variables.scss`
data: `#import "#/variables.scss";`
}
}
}
}
This fixed it for me perfectly.
I don't believe you can globally import a file. I probably wouldn't do this anyway, it's not explicit enough. If someone wants to move that component into another project they would have no idea it relies on that file.
You can, however, make the path management a lot easier. You can add this to your webpack config file...
sassLoader: {
includePaths: [
path.resolve(__dirname, './sass')
]
},
Then you can include files from your projects root /sass directory freely without worrying about the paths.
If you store all your components in the same directory, your path to your settings.scss will always stay the same.
This is the desired functionality of webpack. The principle is to have as little globals as possible and only include what you need, keeping your project lean, efficient, and easy to reason about.
Perhaps you should restructure your components/styling such that you don't have so many custom styles within each Vue component (build your own bootstrap?), therefore you won't have to include a certain stylesheet inside every Vue component.
This doesn't really answer your question but it might guide you towards aligning with the principles behind the tools you've chosen to work with.
Best of luck!
Been there - unfortunately there is not a way to do this without importing the file in each component. To get around this, you could try creating helper classes with color: $some-variable and background-color: $some-variable which may cover some of your use cases.
If you do import a file in each one, make sure it only contains variables. You don't want to include style rules multiple times.
Otherwise, I would create separate .scss files for each component. You can still use .vue templates for html and js, but keep your styles separate. This is probably the most efficient way to do it.
My solution is set the settings.scss file's folder a alias in webpack,
maybe settings.scss is not global need, maybe you are also need a like setting2.scss file, but settings.scss is conflict with setting2.scss, you can only choose to introduce a file in this case.
webpack config like this:
resolve: {
alias: {
'~src': path.resolve(__dirname, '../src'),
'~styles': path.resolve(__dirname, '../src/styles'),
}
so, you can import settings.scss in your component
<style lang="scss">
#import "~styles/settings.scss";
</style>

Using an External Dependency in a Library

I am using wgo for dependency management in Golang (although I think wgo has little to do with this), wgo has a folder structure like this
project/
.gocfg/
gopaths
vendor.json
vendor/
src/
github.com_or_whatever/
I have a library I coded myself which uses an nsq-go type in one of the exported methods:
func AddNsqSubscription(
topic, channel string,
handler nsq.Handler,
config *nsq.Config) error { }
The library is called messi and I import the nsq-go like so "messi/vendor/src/github.com/bitly/go-nsq"
The problem comes when I try to use this library in another project. For instance, in a project called scribe I have the following code (notice the imports):
import (
"scribe/vendor/src/github.com/bitly/go-nsq"
"scribe/vendor/src/messi"
)
//...
nsqHandler := nsq.HandlerFunc(func(message *nsq.Message) error {
msgHandler(MessiMessage{message})
return nil
})
return messi.AddNsqSubscription(destination, subdestination, nsqHandler, nsq.NewConfig())
When I go build the following error is returned:
cannot use nsqHandler (type "scribe/vendor/src/github.com/bitly/go-nsq".HandlerFunc) as type "messi/vendor/src/github.com/bitly/go-nsq".Handler in argument to messi.AddNsqSubscription:
"scribe/vendor/src/github.com/bitly/go-nsq".HandlerFunc does not implement "messi/vendor/src/github.com/bitly/go-nsq".Handler (wrong type for HandleMessage method)
have HandleMessage("scribe/vendor/src/github.com/bitly/go-nsq".Message) error
want HandleMessage("messi/vendor/src/github.com/bitly/go-nsq".Message) error
Why? I do not really know what is going on. The code go-nsq imported is exactly the same, yet golang wants that this code comes from the same folder?
What am I doing wrong?
Packages in Go are identified by full import path, not by name.
For example in the standard library there are two different packages with the same name template but different import paths: text/template and html/template.
You should make sure that go-nsq package is imported using the same path.

Resources