Relative references must start with either "/", "./", or "../" - javascript

I am newbie to lit-element, and when use import to include the library, I am getting error as:
Uncaught TypeError: Failed to resolve module specifier "lit-element".
Relative references must start with either "/", "./", or "../".
Please provide any alternatives/solutions.
import { LitElement, html } from 'lit-element';
class MyElement extends LitElement {
render(){
return html`
<div>
<p>A paragraph</p>
</div>
`;
}
}
customElements.define('my-element', MyElement);

This doesn't work because js imports must reference a specific file with either a relative path or an absolute path, assuming your project structure is something like the following:
/node_modules
/lit-element
/other-library
/src
/components
my-element.js
index.html
From my-element.js, your import would be
import {LitElement, html} from '../../node_modules/lit-element/lit-element.js'
However, since this kind of configuration is confusing and you'll probably end up setting a build script sometime too, the recommendation would be to keep your imports as they are right now and use a dev server that remaps your imports to node_modules like open-wc's web server
Update (Feb. 2021): The web server mentioned on this question has gone through a few iterations and improvements. The current package is #web/dev-server

As you probably know, this type of import is known as 'bare import':
import { LitElement, html } from 'lit-element';
And the error happens because web browsers cannot resolve bare imports by themselves.
I don't know what webserver are you using for developing, but a good way of avoid this type of warnings is choose one that could manage this type of imports, for example web-dev-server
There are other approaches, using, for example tools like Webpack, Polymer-cli, Open Web Components, etc, as this article explains, but, IMO, the web-dev-server option is a very good one for start.

I tried webpack for this issue and that works fine for me.
Here is how I set up webpack on my node javascript project.
First, you need to install the following packages on your project
npm install --save-dev webpack
npm install --save-dev html-webpack-plugin
npm install --save-dev css-loader
npm install --save-dev style-loader
Then, you have to create webpack.config.cjs on your project root and paste the following code into it. (please change file paths as your file structure)
const path = require('path');
const HtmlWebpack = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
},
plugins:[
new HtmlWebpack({
template:path.resolve(__dirname,'./src/template/index.html')
})
],
module:{
rules:[
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource"
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
]
},
devServer:{
port:8080,
hot: true,
static: {
directory: path.join(__dirname, 'dist'),
},
compress: true,
client: {
progress: true,
},
}
}
then add this line to your package.json file
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server --open",
},
now open a terminal on your project root and run npm run dev on it.

You can serve bare module imports with polimer-cli.
a. install it: npm install --save-dev polymer-cli
b. Create polymer.json in your project with roughly contens:
{
"entrypoint": "index.html",
"shell": "app.js",
"npm": true
}
c. do polymer serve

Related

Read the consumer package.json from a package built using webpack in prepare script

I have a library that uses webpack to be bundled, I need to read the consumer package.json config passed to the library.
I tried:
externals: [
{
'global-package': path.resolve(__dirname, '/../../../package.json')
}
]
The library package.json scripts section is like this:
"scripts": {
"prepare": "webpack --mode=production"
}
But when I try to install the package by installing the consumer app, It consider the external path in:
/home/user/.npm
Can you tell me how can I achieve that please?

How to get webpack to include the generated declaration files for a Typescript Nodejs (not browser) project (and how to consume)

I have 2 typescript projects, 1 depends on the other. I can generate the typescript declaration files by setting "declaration": true in tsconfig (which would be applicable to both projects). I also set "outDir" to "./dist". I can see plenty of generated declaration files emitted to the dist folder.
I am also using webpack. But how do I get wepack to include all those declaration files in the bundle so that the client can consume it?
So my tsconfig looks like this:
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"esModuleInterop": true,
"module": "commonjs",
"moduleResolution": "Node",
"noImplicitAny": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es5",
"declaration": true,
"outDir": "./dist",
"types": [
"mocha", "node", "./dist/index.d.ts"
],
"lib": [
"es5",
"es2015",
"es6",
"dom"
]
},
"include": [
"lib/**/*", "tests/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
However, this is not working. The see the following error message:
ERROR in /Users/Plastikfan/dev/github/js/jaxom/tsconfig.json
[tsl] ERROR
TS2688: Cannot find type definition file for './dist/index.d.ts'.
Actually, when I look at this:
"types": [
"mocha", "node", "./dist/index.d.ts"
],
this makes me concerned, because /dist/index.d.ts is an output of the webpack/typescript build process, so how can the build see its content at the beginning of the build process when presumably it would not exist. To me this doesnt seem right, so how do I declare that "./dist/index.d.ts" are the declarations for the project?
Then once this is fixed, how does the typescript client consume the typescript/javascript package; ie I have another project (zenobia) also a typescript project, which needs to consume the typescript project from npm, so what do I need to do to get this to work properly? Jaxom is the source typescript project to be consumed and in it's index file, its exporting all the client facing declarations actually it looks like this:
index.ts:
export * from './types';
export * from './specService/spec-option-service.class';
export * from './converter/xpath-converter.class';
which is the same as the corresponding generated dist/index.d.ts
On the cosuming side (zenobia) I know I need some kind of triple slash directive and an import statement, but am going round in circles not getting it right.
The tsconfig in zenobia is the same as jaxom (as I show above).
The import on the client looks like this:
import * as Jaxom from 'jaxom';
so I would expect all the definitions exported to be available on Jaxom. This import should work because its typescript. If it was js, then this wouldn't work for Nodejs projects.
The documentation I have read is either ambiguous to me, or the explanation I require sits somewhere in between webpack and typescript with neither explaining the full integration properly or making assumptions.
In Jaxom, I have 2 webpack configs (1 for the production code and the other for the tests). This is the pattern I've used/am using for all my webpack/typescript projects.
production webpack config for Jaxom:
module.exports = env => {
const { getIfUtils } = require('webpack-config-utils');
const nodeExternals = require('webpack-node-externals');
const { ifProduction } = getIfUtils(env);
const mode = ifProduction('production', 'development');
console.log('>>> Jaxom Webpack Environment mode: ' + env.mode);
return {
entry: {
index: './lib/index.ts'
},
target: 'node',
externals: [nodeExternals()],
mode: mode,
module: {
rules: [
{
test: /\.ts(x?)$/,
use: 'ts-loader'
},
{
test: /\.json$/,
use: 'json-loader'
}
]
},
plugins: [
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
new webpack.BannerPlugin({
banner: '#!/usr/bin/env node',
raw: true
})
],
resolve: {
extensions: ['.ts', '.json']
},
watchOptions: {
ignored: /node_modules/
},
output: {
filename: 'jaxom-bundle.js',
sourceMapFilename: 'jaxom-bundle.js.map',
path: path.join(__dirname, 'dist'),
libraryTarget: 'commonjs'
}
};
};
And the webpack config for the tests
module.exports = {
devtool: 'source-map',
mode: 'development',
entry: ['./tests/all-tests-entry.js', './lib'],
target: 'node',
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.xml$/i,
use: 'raw-loader'
},
{ test: /\.ts(x?)$/, loader: 'ts-loader' },
{ test: /\.json$/, loader: 'json-loader' }
]
},
resolve: {
extensions: ['.ts', '.json']
},
watchOptions: {
ignored: /node_modules/
},
output: {
filename: 'jaxom-test-bundle.js',
sourceMapFilename: 'jaxom-test-bundle.js.map',
path: path.resolve(__dirname, 'dist'),
libraryTarget: 'commonjs'
}
};
For other beginners stumbling on this issue, the problem of not being able to consume types from the clients perspective was caused by a multitude of issues in the source package, explained as follows.
1) Actually, there was an issue only made apparent by the package.json which was not included in the original post, but it amounted to this:
there are 2 build streams, 1 for the source code and the other for tests (in my package.json these are represented by the 2 separate scripts: "build:d" for dev source code [produces ./dist/jaxom-bundle.js] build and "build:t" for test code build [produces ./dist/jaxom-test-bundle.js]. Both of these scripts depend on a "clean" script which makes use of rimraf to remove existing built files (in "dist/" folder). With my current build setup, building the tests removed all existing built files then built the test bundle. The source bundle was missing.
This meant that when I went to package the build (npm pack to create the tar ball that is published to npm registry), if I had just run the test build prior to publish, the test bundled which includes all the tests would be packaged. This is not what I intended. The simple fix for this scenario was to ensure that just prior to npm pack/publish, the source bundle should be built and this makes itself apparent when you look at the build: ie, you can see the included type files. For those devs just starting out this is really important to realise. Before publishing an npm package (particularly for a new package), you should go through this step of using npm pack, and then extract its contents to see what's in it, or simply take good notice of the result of npm pack and observe whats in the package.
Take a look at the following output of npm pack for the source and test bundles:
source bundle (./dist/jaxom-bundle.js):
λ ~/dev/github/js/jaxom/ feature/define-exports* npm pack
npm notice
npm notice 📦 jaxom#0.0.1
npm notice === Tarball Contents ===
npm notice 1.1kB LICENSE
npm notice 165.5kB dist/jaxom-bundle.js
npm notice 3.2kB package.json
npm notice 99B README.md
npm notice 455B typings/exceptions.d.ts
npm notice 133B typings/index.d.ts
npm notice 1.1kB typings/normaliser/normaliser.class.d.ts
npm notice 1.8kB typings/specService/spec-option-service.class.d.ts
npm notice 9.4kB typings/transformer/transformer.class.d.ts
npm notice 2.5kB typings/types.d.ts
npm notice 1.3kB typings/converter/xpath-converter.class.d.ts
npm notice 5.6kB typings/converter/xpath-converter.impl.d.ts
npm notice === Tarball Details ===
npm notice name: jaxom
npm notice version: 0.0.1
npm notice filename: jaxom-0.0.1.tgz
npm notice package size: 50.5 kB
npm notice unpacked size: 192.2 kB
npm notice shasum: c43be4000932201c0ca077aeb3f102bd0130eef5
npm notice integrity: sha512-96HaZbSHn7kCc[...]rS0K4pLxDMLPA==
npm notice total files: 12
npm notice
jaxom-0.0.1.tgz
λ ~/dev/github/js/jaxom/
test bundle (./dist/jaxom-test-bundle.js) polluted with test classes (spec.d.ts):
λ ~/dev/github/js/jaxom/ feature/define-exports* npm pack
npm notice
npm notice 📦 jaxom#0.0.1
npm notice === Tarball Contents ===
npm notice 1.1kB LICENSE
npm notice 165.5kB dist/jaxom-bundle.js
npm notice 186.0kB dist/jaxom-test-bundle.js
npm notice 3.2kB package.json
npm notice 253.4kB dist/jaxom-test-bundle.js.map
npm notice 99B README.md
npm notice 455B typings/exceptions.d.ts
npm notice 455B typings/lib/exceptions.d.ts
npm notice 133B typings/index.d.ts
npm notice 133B typings/lib/index.d.ts
npm notice 1.1kB typings/lib/normaliser/normaliser.class.d.ts
npm notice 1.1kB typings/normaliser/normaliser.class.d.ts
npm notice 11B typings/tests/normaliser/normaliser.class.spec.d.ts
npm notice 1.8kB typings/lib/specService/spec-option-service.class.d.ts
npm notice 1.8kB typings/specService/spec-option-service.class.d.ts
npm notice 20B typings/tests/specService/spec-option-service.class.spec.d.ts
npm notice 329B typings/tests/test-helpers.d.ts
npm notice 9.4kB typings/lib/transformer/transformer.class.d.ts
npm notice 9.4kB typings/transformer/transformer.class.d.ts
npm notice 20B typings/tests/transformer/transformer.class.spec.d.ts
npm notice 2.5kB typings/lib/types.d.ts
npm notice 2.5kB typings/types.d.ts
npm notice 1.3kB typings/converter/xpath-converter.class.d.ts
npm notice 1.3kB typings/lib/converter/xpath-converter.class.d.ts
npm notice 20B typings/tests/converter/xpath-converter.class.spec.d.ts
npm notice 5.6kB typings/converter/xpath-converter.impl.d.ts
npm notice 5.6kB typings/lib/converter/xpath-converter.impl.d.ts
npm notice 20B typings/tests/converter/xpath-converter.impl.spec.d.ts
npm notice === Tarball Details ===
npm notice name: jaxom
npm notice version: 0.0.1
npm notice filename: jaxom-0.0.1.tgz
npm notice package size: 115.6 kB
npm notice unpacked size: 654.3 kB
npm notice shasum: 8433700d3378bf2ab4ff3798a93e7dbb98baee86
npm notice integrity: sha512-cQ9RUCLwHMOuq[...]xS4kMJe/4jPqQ==
npm notice total files: 28
npm notice
jaxom-0.0.1.tgz
λ ~/dev/github/js/jaxom/
I think the best solution to the above issue would be to have a specific publish script that builds the correct bundle prior to publishing to npm. I found a couple of good articles than explain this well: Step by step: Building and publishing an NPM Typescript package or The 30-second guide to publishing a TypeScript package to NPM
2) Types in a separate folder (my bad!).
having read a plethora of articles on the subject, I came to the miguided conclusion that is was a good idea to put the generated types into a separate folder than the resultant ./dist js bundles. This just makes using the library for the user more awkward and not intuitive to use. Instead of importing jaxom with: "import * as jaxom from 'jaxom'", you would need to use "import * as jaxom from 'jaxom/typings'" (where "typings" is the name of the directory you export types to defined by type/typings entry in jaxom's package.json. This is just not a good idea and not what I intended.
Best just let the types be generated into the same folder as your main bundle, in this case ./dist.

How can I import React Components as a package/module from some other(non-project) directory?

I have a couple of React Components in a folder, which is not a react project. The Directory Structure i am following for components is:
~/components/Component1/index.jsx
~/components/Component2/index.jsx
Now I have a React project (built with create-react-app), named "myapp" I want to import those React Components as a package or module in my project.
I have tried mentioning a dependency in my package.json, but gives an error, because I can't mention absolute paths in package.json.
I don't want to publish these components as a npm package.
Kindly help me with this
The problem was:
I was trying to wrap material-ui components like iconButton, iconMenu, etc. to make the components easy to use programatically. To put them into a git repository I need a example directory with a seperate react project using the components I developed. So, I need to develop a package that hold components' definitions and exporting them to be used in other project. I want to keep my implementations private so I cannot even publish it to npm.js.
[you can see the question statement for thorough understanding of thr ptoblem.]
Coming to the solution help me doing the needed, I created a new project with yarn adding minimal dependencies. i.e.
babel
babel-cli
babel-core
babel-loader
babel-preset-es2015
babel-preset-react
babel-preset-stage-2
html-webpack-plugin
raw-loader
webpack
webpack-dev-server
and then devDependencies
react
react-dom
material-ui [occasional]
After the installations, [HERE COMES THE PART] I created a webpack.config.js with following script:
const path = require('path')
const webpack = require('webpack')
module.exports = {
devtool: 'cheap-eval-source-map',
entry: './docs/entry.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
alias: {
genericcomponents: path.join(__dirname, 'src')
}
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
}
]
},
devServer: {
contentBase: 'docs/'
}
}
In the code above, after mentioning the output the entry, devtool and output of the transpilation process. I actually have another thing to define, which is alias, I defined the alias with the directory holding the components.
Now this package will hold all the components with the name I provided in the alias parameter.
After that I mentioned loaders for transpilation and file format to jsx, so It will accept the source with JSX Syntax.
And at last I mentioned my the directory where I placed my index.html and entry.js file.
Following is the directory structure of my project:
I have my App.jsx Component in docs folder. which can now import any of the components in the components folder by the giving the package name.
You are welcome to discuss of any of the problem occurred in the above solution.
I know the answer might sound very basic but is there any reason why don't you just copy paste the components into the new app and just use them as any other component ?

Compile/transpile code while developing React app

I am developing an app in React.
Until now I have just included
<script src='//unpkg.com/react#15/dist/react.min.js'>
<script src='//unpkg.com/react-dom#15/dist/react-dom.min.js'>
<script src='//unpkg.com/babel-standalone#6/babel.min.js'>
and then I neither had to use
import React from 'react';
import ReactDOM from 'react-dom';
since everything was loaded nor had to compile anything since babel compiled it in real-time.
However, when I want to include third-party libraries installed with npm, it seems I have to use import. For instance, if I install react-dates with npm-install react-dates --save and want to include it with
import { DateRangePicker, SingleDatePicker, DayPickerRangeController } from 'react-dates';
I get the error
Uncaught ReferenceError: require is not defined
I guess it's because I don't use RequireJS, Webpack, Gulp or anything.
What is the preferred way to be able to include components while developing, so I don't have to compile my code everytime I did a small change?
You can use webpack to configure your code, and run it in watch mode or use
webpack-dev-server during development so, that will allow you to compile your code automatically any time you do a small change
Your webpack.config.js should look something like
var debug=process.env.NODE_ENV !== "production";
var path=require("path");
var webpack=require("webpack");
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : null,
entry: "./js/index.js",
module: {
rules: [{
test: /\.jsx?$/,
exclude: [/node_modules/],
use: [{
loader: "babel-loader",
options: {presets: ["stage-0","es2015","react"]}
}]
}]
},
output: {
path: __dirname + "/src",
filename: "bundle.js"
},
plugins: debug? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({mangle: false, sourcemap: false})
]
}
And in your package.json, you can define scripts
"scripts": {
"start": "webpack-dev-server --content-base src",
"build": "webpack --watch"
}
If you run a npm run build command webpack will start in watch mode and you won't need to recompile your code again and again.
or you can run npm start for using webpack-dev-server in development mode.
See how to set up webpack here

React webpack / browserify "unexpected token"

I have this npm module that I created and every time I try to include it to see if it works I get this error:
Unexpected token <
You may need an appropriate loader to handle this file type.
I've used react-starterkit and included it in main.js like so
var ReactDOM = require('react-dom');
var ColorPicker = require('color-picker-react');
ReactDOM.render(<ColorPicker />, document.getElementById('app'));
then when i run gulp which runs webpack I get the error. Here's the webpack.config.js
module.exports.getConfig = function(type) {
var isDev = type === 'development';
var config = {
entry: './app/scripts/main.js',
output: {
path: __dirname,
filename: 'main.js'
},
debug : isDev,
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}]
}
};
if(isDev){
config.devtool = 'eval';
}
return config;
}
I've tried everything I could think of and still can't get it to work. I'm not using ES6 anywhere and I've tried many different react starter kits but I just can't get it to work. Please help!!!
P.S. I am able to get the project to run when I clone it locally and build out app.js with browserify like so: browserify -t [ babelify --presets [ react ] ] app.js -o bundle.js
To solve the problem you need to remove the line exclude: /node_modules/ if you are not the author of the npm module (But you should go with another module).
The component color-picker-react doesn't seem to have a release build or script that compile the jsx. So you need to do it by your own and compile the jsx file on the fly using wepack.
Instead of just removing the exclude: /node_modules/
You can exclude all /node_modules/ except the /node_modules/color-picker-react folder by using a regex pattern :
//will exclude all modules except `color-picker-react`
exclude: /node_modules\/(?!color-picker-react).*\//,
EDIT Basics for creating a npm module:
A correct setup for a npm module is to add a prepublish script to
ensure compilation happens automatically before uploading to NPM.
Thus when you push your module to npm the users doesn't need to compile the module they can just require it.
Taking an example of a node_module:
https://github.com/securingsincity/react-ace/blob/master/package.json
The package.json file is saying which file is the entry point when you required the module
"main": "lib/ace.js",
You can see in the github repository that the lib folder doesn't exist because added to the .gitignore but the line
"prepublish": "npm run clean && npm run build"
is run before uploading to NPM so on the npm repository the lib/ folder exist and you can see it when you do npm install --save react-ace the lib folder appears in the node_modules/react-ace/ folder
A great link that explains how to build npm modules in es6 for example http://javascriptplayground.com/blog/2015/10/authoring-modules-in-es6/
EDIT explain what needs to be done on react-color-picker module :
Sorry i didn't see that you was the author of the module so you should go with the solution below.
The react-color-picker for example doesn't have a prepublish script and the main file is index.js which is
var ColorPicker = require('./colorpicker.js'); // require a file with jsx will throw an error if not precompiled
module.exports = ColorPicker;
So a syntax error is thrown.
To be able to use the npm module in your other applications :
Create a webpack config for the npm module to handle the conversion of your react component written using jsx (you can take some of the webpack configs of this module https://github.com/securingsincity/react-ace set libraryTarget: 'umd' you module will be more easy to consume from various module systems (global, AMD, CommonJS).)
add a prepublish script that output a precompiled version of the color picker (lib/pickedprecompiled.js)
change the main to "main": "lib/pickedprecompiled.js",

Categories

Resources