Webpack - Folder Access Outside Application Folder - javascript

I have code base, the folder structure for which looks like this :
|- build\
|- node_modules\
|- apps\
|--- app_no_1\
|----- index.js
|- src\
|--- modules\
|----- form-login\
|------- Form.jsx
|- package.json
|- webpack.config.js
....
The app_no_1\ folder holds the index file for its React app. However, the modules are sat within the src\ folder. When I import the component from the src directory into the app, I get the error:
bundle.js:41448 Uncaught Error: Module parse failed: Unexpected token (15:18)
You may need an appropriate loader to handle this file type.
| // );
Is there some webpack configuration option I am missing which is required for access to files outside the app's folder? My webpack.config.js is this:
const path = require('path');
const merge = require('merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const PATHS = {
app: path.join(__dirname, 'apps'),
appAthenaTrader: path.join(__dirname, 'apps/athenaTrader'),
appAthenaFinancier: path.join(__dirname, 'apps/athenaFinancier'),
build: path.join(__dirname, 'build'),
modules: path.join(__dirname, 'src/modules')
};
const common = {
output: {
path: PATHS.build,
publicPath: '/',
filename: 'bundle.js'
},
resolve: {
alias: {
modules: PATHS.modules
},
extensions: ['.js', '.jsx', '.json'],
modules: [PATHS.modules, 'node_modules']
},
module: {
rules: [
{
test: /\.jsx?$/,
include: PATHS.app,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
]
},
{
test: /\.scss$/,
include: PATHS.app,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(jpg|png)$/,
include: PATHS.app,
use: {
loader: 'file-loader?name=[name].[ext]'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Satoshi Ltd - Athena'
})
]
};
const generateEntry = env => {
const entryVariable = {
entry: {
app: ''
}
};
if (env.app === 'athena-trader') {
entryVariable.entry.app = PATHS.appAthenaTrader;
} else if (env.app === 'athena-financier') {
entryVariable.entry.app = PATHS.appAthenaFinancier;
// } else ...
}
return entryVariable;
};
const devServer = {
devServer: {
stats: 'errors-only',
host: process.env.HOST || 'localhost',
port: process.env.PORT || 3000
},
devtool: 'inline-source-map'
};
const generateConfig = env => {
const entry = generateEntry(env);
if (env.profile === 'development') {
return merge(common, entry, devServer);
}
return merge(common, entry);
};
module.exports = generateConfig(process.env);
I should note that when the folder is brought inside the app_no_1, the app functions fine, i.e. it is able to execute the component & display it. However, the above folder structure is not being accepted for the apps.

The issue is in your babel-loader configuration. Webpack is complaining that it doesn't know how to parse your files (I'm assuming it's JSX).
In your configuration, you have:
module: {
rules: [
{
test: /\.jsx?$/,
include: PATHS.app,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
]
},
// ...
]
include tells webpack to use babel-loader on any files located inside PATHS.app. When it looks at your files located in PATHS.modules, it doesn't use babel-loader. This is when webpack shows that Module parse failed error.
To fix this, you can update your include value to something like this:
include: [PATHS.app, PATHS.modules]
An alternative is to use exclude instead of include.
// assuming you want to only ignore node_modules
exclude: /node_modules/
I also made a barebones example of this on Github.

Related

Can Babel Apply to Selected Files in Webpack Config?

Here is my webpack.config (using webpack 3) below
I have several .js files in entry.
I'd like to find a way to transpile select .js files through babel while excluding others.
I found a way to include all the .js files in the js/ directory through babel.. But how can I exclude the .js files in js/vendor?
const path = require('path');
const webpack = require('webpack');
module.exports = {
context: __dirname,
entry: {
dataviz : '../js/entry-dataviz.js',
template : '../js/entry-viz-template.js',
abc : '../js/entry-viz-abc.js',
sample: '../js/sample.js',
vendor: [
'../js/vendor/bootstrap.min.js',
'../js/vendor/history.js',
'../js/vendor/history.adapter.jquery.js'
]
},
output: {
filename: '[name]-[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
include: [
path.resolve(__dirname, '../js'), <-- including everything in js/directory
],
use: {
loader: 'babel-loader',
options: { presets: 'es2015'}
}
}
]
},
include can accept a function:
include: function (modulePath) {
// inside `js` folder but not `js/vendor`
return true;
}

Webpack can't resolve relative path import express static

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

Building Gatsby components using Webpack cannot transpile Gatsby module

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
}
};

Run Mocha specs from React app in a browser using Webpack and mocha-loader

I have a react App for which I'd like to run its mocha specs (unit-tests) in a browser. I found this SO post and tried to apply same idea to my project. I came up with the following webpack config file:
webpack.config.test.js
const nodeExternals = require('webpack-node-externals');
const path = require('path');
const host = 'localhost';
const port = '8084';
module.exports = {
target: 'web',
externals: [nodeExternals()],
entry: './specs/index.js',
output: {
filename: 'debug.bundle.js',
path: path.join(__dirname, 'tests'),
publicPath: `http://${host}:${port}/tests`,
},
devServer: {
host,
port,
},
module: {
rules: [
{
test: /\.js$/,
loaders: ['react-hot-loader', 'babel-loader'],
enforce: 'pre',
},
{
test: /.+Spec\.js$/,
loaders: ['mocha-loader'],
},
{
test: /(\.css|\.scss)$/,
loader: 'null-loader',
exclude: [
/build/,
],
},
{
test: /(\.jpg|\.jpeg|\.png|\.gif)$/,
loader: 'null-loader',
},
],
},
};
And, after starting the server with:
webpack-dev-server --config webpack.config.test.js
I get the following error in console:
I've read that the problem might be with webpack-node-externals but not really sure what's happening. Any ideas?
I think you will want to use webpack-node-externals only when you bundle files for backend (as described in plugin README). When you use it you forbid it to build all modules from node_modules folder.

Cannot find module "./src/home/home.jsx"

I know there are about 1000 of these here on SO, but they all seem to reference problem with using the npm package manger and node_modules. My file structure (for the relevant files) is like this:
app
|
main.js
|
src
|
home
|
home.jsx
My main.js file is requiring the home.jsx file like this import Home from './src/home/home.jsx';
I have no idea as to why this would be a problem. I checked for extra spaces that I might have had on t he end of "home.jsx," but that wasn't it. This seems so simple, but I cannot for the life of me understand why this is happening.
If it matters at all, I am using webpack to bundle my files.
//webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './main.js',
output: { path: __dirname, filename: 'bundle.js' },
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
},
resolve: {
extensions: ['', '.js', '.jsx']
}
};

Categories