So i have this function. I am trying to get a new Test('selector', {}) from outside this js file, it comes undefined and i can't seem to figure out why.
Do i really need to attach it to the window object ?
Can someone explain this ?
TO mention it works from the same file.
let Test = ((window, document, undefined) => {
class test {
constructor(selector, options) {
this.selector = document.querySelector(selector);
this.options = options;
}
}
return test;
})(window, document);
This is my webpack config file:
module.exports = {
entry: './src/test.js',
module: {
loaders: [
{
test: /\.js?$/,
exclude: / (node_modules) /,
loader: 'babel-loader',
query: {
presets: ['es2015', 'stage-0']
}
}
]
},
output: {
path: __dirname + '/src',
filename: 'test.min.js'
}
}
I was clearly misunderstanding what webpack is doing. Webpack turns all your JavaScript files into modules that are not available in the global namespace. That's why we need to use require/import to load them in. In the above example the Test function was never loaded in and is not defined. The default scoping nature of JavaScript no longer exists.
Related
I have simple app wrote in ES6 for the training purpose. I want to use modules in this app, so I installed webpack and babel. Unfortunetaly, when I try to fire my method, I receive the error:
Uncaught ReferenceError: gas is not defined
at HTMLButtonElement.count (bundle.js:113)
So, 'gas' is my instance of the object.
Here are my files:
main.js
'use strict'
import Gas from "./gas";
const count = document.getElementById("gas-count");
const gas = new Gas();
count.addEventListener("click", gas.count);
gas.js
export default class Gas {
constructor() {
}
count() {
// code
}
printResult(result) {
// code
}
_isValid(dist, price, aver) {
// Code
}
};
Finally, here is my Webpack config:
module.exports = {
// Define entry point
entry: "./src/main.js",
// Define output point
output: {
path: __dirname + "/dist",
filename: "bundle.js"
},
module: {
loaders: [{
test: /\.js$/,
exclude: /(node_modules)/,
loader: "babel-loader",
query: {
presets: ["env"]
}
}]
}
};
I'd be really grateful if someone could give me a hint why it's not working. Thank you in advance.
Context:
I work on a project where the senior programmer decided to reduce the boilerplate code in newly created typescript files. Two examples of this boilerplate code would be importing the React library or the function that fetches and processes our localized strings.
Question:
Is it possible to have imports always available in files placed in certain folders without having to write the import tags every time?
What I've tried:
I've searched and read on the subject and found those links that talk about defining variables to use in the global space:
global.d.ts, global-modifying-module.d.ts, A typescript issue that seems to get it working
However, I was still unable to get it to work. Here is what I've tried:
At the root of the folder where I want React to be always available, I created a global.d.ts file which contains:
import * as R from "react";
declare global{
const React: typeof R;
}
With this file, the resource "React" is supposed to always be available to other files in subsequent folders. My IDE (Webstorm) recognizes that the import is there and allows me to manipulate the variable React without complaining. However, when I try to run the app, I get this error:
ReferenceError: React is not defined
I don't understand what is wrong with the code! Here is an example of the file I'm trying to render:
export default class World extends React.Component<{}, any> {
public render() {
return (<div>Hello world</div>);
}
}
From this stackoverflow question, I was under the impression that the problem could be webpack related. For the sake of completeness, here is the webpack config file we're currently using:
const webpack = require('webpack');
const path = require('path');
const BUILD_DIR = path.resolve(__dirname, './../bundles');
const WEBPACK_ENTRYFILE = path.resolve(__dirname, './../srcReact/ReactWrapper.tsx');
// `CheckerPlugin` is optional. Use it if you want async error reporting.
// We need this plugin to detect a `--watch` mode. It may be removed later
// after https://github.com/webpack/webpack/issues/3460 will be resolved.
const { CheckerPlugin } = require('awesome-typescript-loader');
const config = {
entry: [WEBPACK_ENTRYFILE],
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.less']
},
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
plugins: [
new CheckerPlugin()
],
devtool: 'source-map', // Source maps support ('inline-source-map' also works)
module: {
loaders: [
{
loader: 'url-loader',
exclude: [
/\.html$/,
/\.(js|jsx)$/,
/\.(ts|tsx)$/,
/\.css$/,
/\.less$/,
/\.ttf/,
/\.woff/,
/\.woff2/,
/\.json$/,
/\.svg$/
],
query: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
},
{
loader: 'url-loader',
test: /\.(ttf|woff|woff2)$/
},
{
loader: "style-loader!css-loader!less-loader",
test: /\.less$/
},
{
loader: "style-loader!css-loader",
test: /\.css$/
},
{
loader: "svg-loader",
test: /\.svg$/
},
{
loader: "json-loader",
test: /\.json$/
},
{
loader: "awesome-typescript-loader",
test: /\.(ts|tsx)$/
}
]
}
};
module.exports = config;
I am certain I am missing something. Can anyone help me?
Surely already open followed a tutorial like this
To do this creates a vendor file where you import these types of "global".
./src/vendors.ts;
import "react";
Add this file a to first place at entry parameter:
entry: { 'vendors': './src/vendors.ts', 'main': './src/main.ts' }
And add CommonChunkPlugins:
plugins: [ new CommonsChunkPlugin({
name: 'vendors'
}),
Like this in AngularClass with polyfills.
Begin work with webpack and stack. My generated html file consist string with event onclick. But my html file doest't see function in generated file bundle.js. Bundle js file conected successfully(console.log works). But if i write <script>function bar()...</script> in html, onclick work. Help.
Try connect file in head, beggining body, end of body/file - doesn't see function. Bundle.js generated from main.js:
require("path to css...");
function bar(){...};
String in html:
<div class="foo" onclick="bar()">...</div>
Bundle.js:
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: "dist",
filename: "bundle.js"
},
module: {
loaders: [
{
test: /\.js$/,
loader: "babel-loader",
options: { presets: ["es2015"] }
,
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style','css')
},
{
test: /\.jade$/,
loader: "jade"
}]
},
plugins: [
new ExtractTextPlugin("main.css"),
new HtmlWebpackPlugin({
template: './src/jade/index.jade'
})
]
};
That's because you don't export your function. One of the main benefits of WebPack is that functions aren't put on global scope by default. Add export default to your declaration:
export default function bar(){...};
With webpack, you must explicitly put names in the global namespace. There are probably many ways to do this, but the easiest is to use the browser's window object:
window.bar = function(){...};
or
function bar(){...};
window.bar = bar;
I'm trying to dynamically include a .js file at webpack compile time.
I don't want to use a context to load environmental variables, because I don't these magic variables in my code.
What I'm trying to do is use the val loader to execute a module. There use an environment variable to decide what module to import. And export that module.
However, this is causing other loaders to throw errors.
Here's my dir layout
--base
--src
app.js
test.js
webpack.config.js
rawr.js
Here my webpack.config.js file
var path = require('path');
var webpack = require('webpack');
// var process = require('process');
var env = require(process.env.NODE_ENV || './devConf.js');
module.exports = {
// Specify logical root of the sourcecode
plugins: [
new webpack.DefinePlugin(env)
],
context: path.join(__dirname, '/src'),
entry: {
app: ['bootstrap.js'],
},
// Specify where to put the results
output: {
path: path.join(__dirname, '/dist'),
filename: 'build.js'
},
// Specify logical root of package imports so as to avoid relative path everywhere
resolve: {
root: path.join(__dirname, '/src'),
// What files we want to be able to import
extensions: ['', '.js', '.css', '.less'],
},
module: {
preLoaders: [
// Lint all js before compiling
/*{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader'
}*/
],
loaders: [
{
test: /\.js$/,
query: {
presets: ['es2015']
},
exclude: /node_modules/,
loader: 'babel'
},
{
test: /\.tpl\.html$/,
exclude: /node_modules/,
loader: 'ngtemplate?relativeTo=/src/!html'
},
{
test: /\.scss$/,
loaders: ["style", "css", "sass"]
},
{
test: /\.css$/,
loaders: ["style", "css"]
}
]
},
// Dev server settings
devServer: {
contentBase: path.join(__dirname, '/dist'),
noInfo: false,
hot: true
},
// ESLint config
eslint: {
configFile: path.join(__dirname, '.eslintrc')
}
};
My js files look like this
// app.js
let b = require('val!test.js');
// test.js
var process = require('process');
loadedModule = require(process.env.NODE_ENV) // NODE_ENV='./rawr.js'
export const myString = loadedModule
// rawr.js
module.exports.test = "hello world";
The exception I'm getting:
ERROR in ./src/app/app.js
Module parse failed: /home/smaug/Projects/angular-template/node_modules/babel-loader/index.js?{"presets":["es2015"]}!/home/smaug/Projects/angular-template/src/app/app.js Line 1: Unexpected identifier
You may need an appropriate loader to handle this file type.
| 'use strict';
|
| require('angular-animate');
# ./src/bootstrap.js 7:0-18
It has nothing to do with what I'm trying to do. But if I remove the require('val!...') statment, it goes away.
Any ideas?
UPDATE:
If I change the require statement to be
let b = require('val!./test.js');
I get the following error:
ERROR in ./~/val-loader!./src/app/test.js
Module build failed: Error: Final loader didn't return a Buffer or String
at DependenciesBlock.onModuleBuild (/home/smaug/Projects/angular-template/node_modules/webpack-core/lib/NormalModuleMixin.js:299:42)
at nextLoader (/home/smaug/Projects/angular-template/node_modules/webpack-core/lib/NormalModuleMixin.js:275:25)
at /home/smaug/Projects/angular-template/node_modules/webpack-core/lib/NormalModuleMixin.js:292:15
at runSyncOrAsync (/home/smaug/Projects/angular-template/node_modules/webpack-core/lib/NormalModuleMixin.js:160:12)
at nextLoader (/home/smaug/Projects/angular-template/node_modules/webpack-core/lib/NormalModuleMixin.js:290:3)
at /home/smaug/Projects/angular-template/node_modules/webpack-core/lib/NormalModuleMixin.js:292:15
at Object.context.callback (/home/smaug/Projects/angular-template/node_modules/webpack-core/lib/NormalModuleMixin.js:148:14)
at Object.module.exports (/home/
// app.js
let b = require('val!./test.js');
This is a very confusing Error Message..
Check for the following mishaps..
import statement is pointing to the exact file;
typo errors in the file name on import statement; importing the
modules which are not present.
check whether you have installed all
the loaders like
css-loader node-sass resolve-url-loader sass-loader\
style-loader url-loader
4.import statement is empty
ex:
import * from '';
5. Services and Providers returning nothing may also cause this error.
test.js is supposed to return a string that contains the code that is supposed to be given to the module that is requiring it. So, for your example, test.js should go from this
var process = require('process');
loadedModule = require(process.env.NODE_ENV) // NODE_ENV='./rawr.js'
export const myString = loadedModule
to this
var process = require('process')
loadedModule = require('raw-loader!' + process.env.NODE_ENV)
export const myString = loadedModule
Using the "raw-loader" you will get the text code from rawr.js rather than the value that rawr.js exports. "val-loader" will then give rawr.js's code to the require in app.js and it will load that text as if it was the text of the file that you were trying to load.
That was probably a terrible explanation, but just remember that when you use val-loader, you need to return a string containing code.
I want to use the css-loader with the 'modules' option of webpack in a React application written in Typescript. This example was my starting point (they are using Babel, webpack and React).
webpack config
var webpack=require('webpack');
var path=require('path');
var ExtractTextPlugin=require("extract-text-webpack-plugin");
module.exports={
entry: ['./src/main.tsx'],
output: {
path: path.resolve(__dirname, "target"),
publicPath: "/assets/",
filename: 'bundle.js'
},
debug: true,
devtool: 'eval-source-map',
plugins: [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({minimize: true})
],
resolve: {
extensions: ['', '.jsx', '.ts', '.js', '.tsx', '.css', '.less']
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader'
},
{
test: /\.tsx$/,
loader: 'react-hot!ts-loader'
}, {
test: /\.jsx$/,
exclude: /(node_modules|bower_components)/,
loader: "react-hot!babel-loader"
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader"
}, {
test: /\.css/,
exclude: /(node_modules|bower_components)/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader')
}
]
},
plugins: [
new ExtractTextPlugin("styles.css", {allChunks: true})
],
postcss: function() {
return [require("postcss-cssnext")()]
}
}
This is a React component I want to style with an accompanying CSS file:
import React = require('react');
import styles = require('../../../css/tree.css')
class Tree extends React.Component<{}, TreeState> {
...
render() {
var components = this.state.components
return (
<div>
<h3 className={styles.h3} >Components</h3>
<div id="tree" className="list-group">
...
</div>
</div>
)
}
}
export = Tree
tree.css
.h3{
color: red;
}
No matter what I'm doing (tried changing the import syntax, tried declaring the 'require' for ts-loader, described here, I always get:
Uncaught Error: Cannot find module "../../../css/tree.css"
at runtime and
error TS2307: Cannot find module '../../../css/tree.css'.
by the TS compiler. Whats happening? Seems to me that css-loader is not even emitting ICSS? Or is it ts-loader behaving wrong?
import has special meaning to TypeScript. It means that TypeScript will attempt to load and understand the thing being imported. The right way is to define require like you mentioned but then var instead of import:
var styles = require('../../../css/tree.css')`
Declare 'require' as per ts-loader documentation.
Use 'require' as generic with < any > type: require< any >("../../../css/tree.css").
*.d.ts file
declare var require: {
<T>(path: string): T;
(paths: string[], callback: (...modules: any[]) => void): void;
ensure: (paths: string[], callback: (require: <T>(path: string) => T) => void) => void;
};
*.tsx file with component
const styles = require<any>("../../../css/tree.css");
...
<h3 className={styles.h3}>Components</h3>
I know it was already answered, but I was struggling with it for a while before I realized I need to use generic type specification, without that I wasn't able to access content of CSS file. (I was getting error: Property 'h3' does not exists on type '{}'.)
I had similar problem.
For me, works import:
import '../../../css/tree.css';
Webpack change this like any other normal imports. It change it to
__webpack_require__(id)
One drawback is that you lost control on style variable.
You can use https://github.com/Quramy/typed-css-modules, which creates .d.ts files from CSS Modules .css files. Please see also https://github.com/css-modules/css-modules/issues/61#issuecomment-220684795
A bit late to game but you can create a file called tree.css.d.ts in the same folder as tree.css that has this line:
export const h3: string;
and still use the import statement import * as styles from ... and you will still getcode completion and compile time checking.
You can either manage these definition files manually or you could integrate typed-css-modules into your build pipeline (https://github.com/Quramy/typed-css-modules)