I have a Webpack angular 2 application and I have a date picker module dependency with a library using Moment. The thing is that if I don't import it like :
<script src="./../node_modules/moment/min/moment.min.js"></script>
a moment is not defined error is raised if I want to use it. I tried to import moment with require but it's not taken into account.
The problem is that the script src tag works in local but in the webpack builded version we need to deploy the path with node_modules doesn't exist anymore. Is there a way to do it other than hard paste moment.min.js in a lib folder?
Add the following code in webpack.conf.js:
resolve: {
alias: {
'moment': 'moment/min/moment.min'
}
}
Now you can simply do, require('moment') in your js file.
Note: By default webpack searches the file in node_modules folder. You can instruct it to look into specific places using modules property of resolve object.
The resulting code would look like:
resolve: {
modules: ['lib/','some_folder/node_modules'...],
alias: {
'moment': 'moment/min/moment.min'
}
}
Related
I have lots of .js files to import in Vue components in my project. Some of these JavaScript files are meant to be used in development mode and they won't be included in production but I am not allowed to delete these files in project. For example;
There are two JavaScript files called authDev.js and authProd.js. Their usage is basically the same but their content are different from each other. Inside of these JavaScript files there are functions and I export them to be able to import in several Vue components.
The first question, If I dynamically export or import them, will webpack include these files when I run npm run build? In other words, let's say I created a JavaScript file but I didn't export it, so I didn't import it to anywhere either. Does webpack understand that this JavaScript file is not used in anywhere of these Vue project and discard it when it builds my project to production? Or does it include every single file that existed in the project?
The second question, is there a way to tell the webpack that those JavaScript files will not be included in dist folder these will... I mean, can I specify files for development and production?
First I thought I could import or export them based on a condition but when I try to put my imports in if statements, it gives me an error and says "imports must be at the top level". So I tried to export them dynamically but couldn't do it either.
Then I try to remove specific blocks of codes in files. There are packages and plugins to remove every console outputs from Vue projects but I couldn't find anything to remove or discard specific lines of codes.
At last, I decided to took a way to include and exclude specific files. Is there a way to do it? If it is, how do I do that? Thanks in advance.
THE SOLUTION (EDITED)
For a quick test, I created two .js files called auth-development.js and auth-production.js in src/assets/js/filename.js location. Here are the contents of them;
auth-production.js
export const auth = {
authLink: "http://production.authlink/something/v1/",
authText: "Production Mode"
}
auth-development.js
export const auth = {
authLink: "http://localhost:8080/something/v1/",
authText: "Development Mode"
}
Then I modified my webpack config which is in the vue.config.js file;
const path = require('path');
module.exports = {
configureWebpack: {
resolve: {
alias: {
'conditionalAuth': path.resolve(__dirname, `src/assets/js/auth-${process.env.NODE_ENV}.js`)
}
}
}
}
Vue was giving "path is undefined" error, I added the top part of the code to handle that error. I used process.env.NODE_ENV to get the words development and production to add the end of my javascript files so that I can define their path.
Then I dynamically imported this conditionalAuth to a test component called "HelloWorld" as follows;
<script>
import * as auth from 'conditionalAuth';
export default {
name: 'HelloWorld',
data(){
return {
auth: auth
}
}
}
</script>
And I used them like this;
<template>
<div>
<p>You are in the {{ auth.auth.authText}}</p>
<p>{{ auth.auth.authLink }}</p>
</div>
</template>
In this way when I npm run serve it imports auth-development.js but if I npm run build and try the index.html in the dist folder on a live server, it only imports the auth-production.js.
At last, when I check the final build, auth-development.js is not built for my dist version of the project. It only imports the production javascript file in the chunk.
Assuming the file names are: auth-development.js and auth-production.js, you can use webpack alias to import file according to environment.
resolve: {
alias: {
'conditionalAuth': path.resolve(__dirname, `path/to/js/auth-${process.env.NODE_ENV}.js`)
},
extensions: ['.js', '.vue', '.json']
}
then you should be able to import the desired file like:
import * as auth from 'conditionalAuth';
The documents talk about using external in the context of the node resolve plugin, but I am not using that. I would like to exclude lit-html (which is native es6 modules) so that those imports remain in the bundle.
In my module I import them with import { html, render } from '../../node_modules/lit-html/lit-html.js'; and it works great in the browser.
I have tried every permutation of path including relative path like rollup --format=esm --file=dist/bundle.js -- src/main.js --external 'node_modules/lit-html/lit-html.js' and just get [!] Error: Could not resolve entry (--external).
It does not even say if the file is found, never mind what the problem is.
Seems your command is wrong, use -i to indicate the input file or try moving -- src/main.js to the end of the command without the dashes.
Regarding the external part, don't think it will work without using the exact id of the import but worth a try.
Using a config file:
module.exports = {
input: 'src/main.js',
external:[
'../../node_modules/lit-html/lit-html.js'
],
output: {
format: 'esm',
file: './dist/bundle.js',
sourcemap: true
}
}
After I change all file from jsx to tsx, I get this error:
./src/components/index.js Module not found: Can't resolve './Header'
in '/Users/khuongpham/WebFrontEnd/home/src/components'
You need to do correct Webpack configuration, add .tsx under resolve property:
....
resolve: {
extensions: ['.js', '.jsx', '.tsx']
}
....
FYI: It seems if you want to integrate TypeScript into React, you still need to install some libraries and development dependencies to let Webpack and React play well.
If you changed all files from jsx to tsx then what is the reason for leaving index.js?
Why don't you change it to index.tsx or at least index.ts?
As far as I'm concerned, ts and js can't directly interact with each other.
If you are writting a ts or tsx file and you want to import a js file (or js library) you will need something called type declaration file which, most of the time, can be found here: https://microsoft.github.io/TypeSearch/
In your case, you are trying to import typescript from javascript and that is probably the problem. Changing index.js to index.ts may help.
Our project is using the webpack resolve.root option to import modules with absolute paths. (avoiding something like ../../../module)
In its current state the project is using babel-loader which works perfectly fine.
My task is to migrate the app to Angular 2.
Therefor I am currently in the process of transitioning to TypeScript.
Somehow it seems like the ts-loader does not work in combination with the resolve.root option of the webpack config.
Example of the webpack.config.js
resolve: {
root: [
path.resolve('./node_modules'),
path.resolve('./app'),
path.resolve('./app/lib'),
]
},
Example of a module import
import AbstractListState from 'states/abstract_list_state';
The states directory is inside the app/lib directory.
Error when executing webpack
ERROR in ./app/mainViews/panel/panel.controller.ts
Module not found: Error: Cannot resolve module 'states/abstract_list_state' in C:\Users\...\Project\app\mainViews\panel
# ./app/mainViews/panel/panel.controller.ts 4:28-65
Pre version 2.0 TypeScript will try to load modules with an absolute path from the node_modules directory. This is because TypeScript's module resultion is per default set to "node". Which means it works like node's require method. So, even if you're using webpack to build your app, TypeScript (and its compiler) will still want to load the files.
In order to let webpack import your modules with absolute path you have to go back and use the require method. This way TypeScript will let webpack import stuff. But of course you will not get any type-inference, autocomplete, ...
Or, you update to the TypeScript 2.0 beta and give this a try: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#module-resolution-enhancements-baseurl-path-mapping-rootdirs-and-tracing
Context
I'm working on a project using Angular2, TS and SystemJS. I've built a simple module loader using SystemJS which allows me to import 'custom' modules like this :
import { NavComponent } from "component#nav";
Maybe it'll be important.
Goal
I would like to import .scss files inside my angular components to be able to do things like that :
#Component({
selector: 'app-view',
styles: [ require('path/to/mainScss/file.scss') ],
template: //...
})
Issue
I've found some examples using webpack but I can't get this works. During searching, I've found this module. It can be interesting because it uses SystemJS like me and I don't have to add webpack to my project.
So I've decided to use it (and I'm not sure if it's possible to use webpack and SystemJS at the same time. require was undefined). I didn't know jspm before using this module, I've always used npm. So I've installed jspm locally (relative to my project) and globally and I've installed the module.
Then, inside a component : import './styles/importer.scss!';. And I get an error here.
Error: SyntaxError: Unexpected token <. I know that this error happens when SystemJS failed to load a module but I can't figure out why.
Why ?!
Why am I trying to do that ?
My module loader allows me to write some modules in separate folders (named like this namepace#name). I can add those folders inside another one named modules/ and then enable/disable modules by editing a configuration file.
So I want my .scss files to be loaded only if a module is enabled. That's why I want to include my sass inside an Angular component. That way, it'll be loaded only if the component is loaded.