I want to bundle a JavaScript project by WebPack but there is more problems in none-module libraries because imported them by 'import' capability,ECMAScript 6 module loader run strict mode by default and it tack more errors.
Question :
How can I import none module libraries without strict mode to bundle them by WebPack?
index.js
import '../examples/js/libs/draco/draco_encoder.js';
import './js/libs/codemirror/codemirror.js';
import './js/libs/codemirror/mode/javascript.js';
import './js/libs/codemirror/mode/glsl.js';
...
webpack.config.js
const path = require('path');
const webpack = require('webpack');
// webpack.config.js
module.exports = {
entry: {
polyfills: './editor/polyfills',
index: './lib/index.js',
},
mode: 'development',
output: {
path: __dirname,
publicPath: '/',
filename: './editor/[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
watchContentBase: true,
publicPath: "/",
contentBase: "./",
hot: true,
port: 8080,
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
};
babel.config.json
{
"presets": [
"#babel/preset-env"
]
}
I tryed :
babel
esmify
browserify
Shimming in WebPack
...
Thanks for your attention.
Webpack enables use of loaders to preprocess files. This allows you to bundle any static resource way beyond JavaScript.
About loaders: Loaders.
You can easily write your own loaders using Node.js : Writing Loader.
For execute JS script once in global context that can solved my problem : Script Loader
Related
I'm working on an outlook addin I have an express server running. I am setting webpack because I need to transpile js to es5 to make it work in Outlook Desktop. Here is the simplified project structure.
/public
/javascripts
ssoAuth.js
/addin
/commmands
commands.js
commands.html
/server
/bin
/helpers
app.js
The public folder is set as a static folder in my express server
app.use(express.static(path.join(__dirname, '../public'),
My problem is in commands.js I import ssoAuth.js with es6 module import with relative path :
import getGraphAccessToken from "/javascripts/ssoAuthES6.js";
It works fine when I run node ./server/app.js and load my outlook addin, but when I want to use Webpack to bundle, the import is not working, I get :
ERROR in ./addin/commands/commands.js
Module not found: Error: Can't resolve '/javascripts/ssoAuth.js'
I can't figure out how to configure webpack to allow the imports from the public folder.
Here are my webpack config files :
webpack.config.js :
const config = {
devtool: "source-map",
entry: {
polyfill: "#babel/polyfill",
commands: "./addin/commands/commands.js"
},
resolve: {
extensions: [".ts", ".tsx", ".html", ".js"]
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
},
{
test: /\.html$/,
exclude: /node_modules/,
use: "html-loader"
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: "file-loader"
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: "commands.html",
template: "./addin/commands/commands.html",
chunks: ["polyfill", "commands"]
})
]};
webpack.server.config.js :
return ({
entry: {
server: './server/bin/www',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
externals: [nodeExternals()],
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new CopyWebpackPlugin([
{
to: "./public",
from: "./public"
}
])
]})
Can you help figure this out ? Is there a better folder structure that I should use to make it work ?
Thanks
You're using an absolute path
import getGraphAccessToken from "/javascripts/ssoAuthES6.js";
// ^ this will look in your topmost directory on your OS
The relative path, from commands.js, would be:
import getGraphAccessToken from "../../javascripts/ssoAuthES6.js";
Alternatively, you can set Webpack to look for modules from your root directory by adding the following to your webpack configuration:
{
// ...
resolve: {
modules: [path.resolve(__dirname, "src"), "node_modules"],
},
// ...
}
Then you can import from your project's root directory from anywhere, like so:
import getGraphAccessToken from "javascripts/ssoAuthES6.js";
Some other points:
Since you're setting the extensions: [".ts", ".tsx", ".html", ".js"], you don't need to provide file extensions for those imports
You specify .ts and .tsx in your webpack config, but you are using .js files. Consider removing the Typescript extensions
If you are using Typescript, you will need to update import paths in your tsconfig.json
You can consider import path aliases in both Webpack and Typescript to be more explicit that your imports are coming from your project root. Instructions here
I am trying to make a library of Gatsby components (using specific Gatsby library rather than general React components).
I have been compiling using just babel but I want to be able to translate any CSS-in-JS and do other things so I am trying to build using Webpack.
When I try to compile the Gatsby component it fails in the Gatsby module. I know Gatsby is untranspiled ES6 so I included node_modules in my webpack configuration to transpile but I still:
ERROR in ./node_modules/gatsby/cache-dir/gatsby-browser-entry.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /Users/kylecalica/Code/gatsby-learn/gatsby-components/node_modules/gatsby/cache-dir/gatsby-browser-entry.js: Unexpected token (25:4)
23 |
24 | return (
> 25 | <React.Fragment>
| ^
26 | {finalData && render(finalData)}
27 | {!finalData && <div>Loading (StaticQuery)</div>}
28 | </React.Fragment>
Webpack:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const htmlWebpackPlugin = new HtmlWebpackPlugin({
filename: "index.html"
});
module.exports = {
entry: path.join(__dirname, "/src/index.js"),
output: {
filename: 'main.js',
path: path.resolve(__dirname, "/webpack/dist")
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
]
},
plugins: [htmlWebpackPlugin],
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 9000,
open: true
}
};
I am currently trying to take what Gatsby says to do to Storybook in my code but it's hard to figure out how to translate this from their strange way into mine?
Storybook's way of webpack:
module.exports = ({ config }) => {
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
// use installed babel-loader which is v8.0-beta (which is meant to work with #babel/core#7)
config.module.rules[0].use[0].loader = require.resolve("babel-loader")
// use #babel/preset-react for JSX and env (instead of staged presets)
config.module.rules[0].use[0].options.presets = [
require.resolve("#babel/preset-react"),
require.resolve("#babel/preset-env"),
]
config.module.rules[0].use[0].options.plugins = [
// use #babel/plugin-proposal-class-properties for class arrow functions
require.resolve("#babel/plugin-proposal-class-properties"),
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
require.resolve("babel-plugin-remove-graphql-queries"),
]
// Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
config.resolve.mainFields = ["browser", "module", "main"]
return config
}
.babelrc :
{
"presets": [
"babel-preset-gatsby-package",
"#babel/preset-react",
"#babel/preset-env"
]
}
I solved this by converting what Storybook's webpack module had. I am still putting it through testing however but it compiles fine for now:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const htmlWebpackPlugin = new HtmlWebpackPlugin({
filename: "index.html"
});
module.exports = {
entry: path.join(__dirname, "/src/index.js"),
output: {
filename: 'index.js',
path: path.resolve(__dirname, "webpack")
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader",
options: {
presets: ["babel-preset-gatsby-package"],
plugins: ["#babel/plugin-proposal-class-properties"]
},
},
exclude: [/node_modules\/(?!(gatsby)\/)/],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
]
},
plugins: [htmlWebpackPlugin],
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 9000,
open: true
}
};
I am enhancing a website with ReactJS.
My folder structure looks something like this:
_npm
node_modules
package.json
package-lock.json
webpack.config.js
_resources
js
react
reactapp1.js
reactapp2.js
components
FormDisplay.js
I want to import a custom reactjs package into the FormDisplay component.
When I enter:
import PlacesAutocomplete from 'react-places-autocomplete'
This doesn't work. But if I enter:
import PlacesAutocomplete from "./../../../_npm/node_modules/react-places-autocomplete";
This works. I understand why this is the case. I was wondering if there was a way that I can just enter:
import PlacesAutocomplete from 'react-places-autocomplete';
How do I make it work with just that line of code, without having to find the path to node_modules folder?
My webpack config:
const path = require("path");
const webpack = require("webpack");
const PATHS = {
app: path.join(__dirname, "../_resources/react/"),
build: path.join(__dirname, '../wordpress_site/wp-content/themes/custom_theme/assets/js/'),
};
module.exports = {
entry: {
reactapp1: path.join(PATHS.app, "reactapp1.js"),
reactapp2: path.join(PATHS.app, "reactapp2.js")
},
output: {
filename: "[name].bundle.js",
//path: path.join(__dirname, "dist")
path: PATHS.build
},
module:{
rules: [
{
test: /\.js?$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["env", "react"],
plugins: ["transform-class-properties"]
}
}
}
]// rules array
}, // module
}
Have you tried using webpack's resolve-modules?
resolve: {
modules: ['_npm/node_modules']
}
Might work
I have two webpack 2 projects
The 1st one, let's call it lib1 is a library of reusable React components. In the webpack config it is exported as a library with the name lib1. The project lists react and react-dom as external dependencies.
The 2nd one, let's call it proj1 is an app that uses lib1. Because lib1 is served on a cdn, it's listed as an external dependency. The project also depends on react and react-dom. Using CommonsChunkPlugin I generare a vendor.js that includes react and react-dom (and eventually other dependencies).
When I run proj1 in the browser, the code inside lib1 fails because it can't find react. The libraries are loaded in this order:
<script src="dist/vendor.js"></script>
<script src="http://cdn.com/lib1/lib1.js"></script>
<script src="dist/bundle.js"></script>
I guess the issue is that react and react-dom are not exported by my vendor.js file.
I tried using the library option like this (int proj1):
library: "[name]",
libraryTarget: "umd"
But it creates window.vendor not window.React and window.ReactDOM.
How do I do that?
lib1 config
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, "dist"), // string
filename: "bundle.js",
publicPath: "/dist/",
library: "lib1",
libraryTarget: "umd",
},
module: {
rules: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: path.resolve(__dirname, "node_modules"),
}]
},
externals: ["react", "react-dom"],
};
proj1 config
var webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {
bundle : './src/index.js',
vendor : ['react', 'react-dom']
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
publicPath: "/dist/",
library: "[name]",
libraryTarget: "umd",
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
})
],
module: {
rules: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: path.resolve(__dirname, "node_modules"),
}]
},
externals: ["lib1"],
devtool: "source-map"
};
I have a strange issue using webpack.
This my webpack.config.js:
import webpack from "webpack";
import path from "path";
//not working: import ExtractTextPlugin from "extract-text-webpack-plugin";
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const GLOBALS = {
"process.env.NODE_ENV": JSON.stringify("production"),
__DEV__: false
};
export default {
debug: true,
devtool: "source-map",
noInfo: true,
entry: "./src/bootstrap",
target: "web",
output: {
path: path.join(__dirname, "dist"),
publicPath: "/",
filename: "bundle.js"
},
resolve: {
root: path.resolve(__dirname),
alias: {
"~": "src"
},
extensions: ["", ".js", ".jsx"]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin(GLOBALS),
new ExtractTextPlugin("styles.css"),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin()
],
module: {
loaders: [
{ test: /\.jsx?$/, include: path.join(__dirname, "src"), loaders: ["babel"] },
{ test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: "file" },
{ test: /\.(woff|woff2)$/, loader: "file-loader?prefix=font/&limit=5000" },
{ test: /\.ttf(\?v=\d+.\d+.\d+)?$/, loader: "file-loader?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: "file-loader?limit=10000&mimetype=image/svg+xml" },
{ test: /\.(jpe?g|png|gif)$/i, loaders: ["file"] },
{ test: /\.ico$/, loader: "file-loader?name=[name].[ext]" },
{
test: /(\.css|\.scss)$/,
loader: ExtractTextPlugin.extract("css?sourceMap!sass?sourceMap")
}
]
}
};
As you can see: I set up an alias "~" pointing to my "src" directory.
According to webpack documentation I should be able to import modules this way:
import { ServiceStub } from "~/utilities/service-stub";
HINT: File service-stub.js sits here: [__dirname]/src/utilities/service-stub.js.
However, this does not work since webpack is throwing an error ("Path not found.").
When I userequire instead of import, everything works fine:
const { ServiceStub } = require("~/utilities/service-stub");
The same issue is in webpack.config.js itself:
import webpack from "webpack";
import path from "path";
//not working: import ExtractTextPlugin from "extract-text-webpack-plugin";
const ExtractTextPlugin = require("extract-text-webpack-plugin");
Here some modules import well with import (modules webpack and path), some do not (module extract-text-webpack-plugin).
I worked through dozens of forums, but found no solution yet.
The problem is ESLint - not webpack.
When you are using aliases in webpack like this
resolve: {
root: path.resolve(__dirname),
alias: {
"~": "src"
},
extensions: ["", ".js", ".jsx"]
}
and you are importing this way
import { ServiceStub } from "~/services/service-stub";
ESLint cannot resolve the alias and reports an error.
To get it work you must tell ESLint to ignore some rule with "import/no-unresolved": 0. This seems to be okay because if an imported file is actually missing, webpack reports an error itself.