Hi I am currently using webpack to bundle my project files into a single file. However, I do not want webpack to bundle my config.js file where all my config is set. I would like to this remain separate in the output folder but not sure out to achieve this.
my current setup is
//index.js file
#!/usr/bin/env node
'use strict';
let config = require('config.js);
let read = require('read.js);
console.log('i am running through command line');
//read.js file
'use strict'
console.log('read a text file');
//config.js
'use strict';
module.exports = {
name: 'test'
}
//webpack.config.js
let webpack = require('webpack');
let path = require('path');
let fs = require('fs');
let nodeModules = {};
fs.readdirSync('node_modules')
.filter(function (x) {
return [ '.bin' ].indexOf(x) === -1;
})
.forEach(function (mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = {
entry: [ 'babel-polyfill', './index.js' ],
target: 'node',
node: {
__dirname: true
},
output: {
path: path.join(__dirname, 'webpack_bundle'),
filename: '[name].js',
libraryTarget: 'commonjs'
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'shebang-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: [ 'es2015' ]
}
} ]
},
resolve: {
extensions: [ '.js' ]
},
plugins: [
new webpack.BannerPlugin({banner: '#!/usr/bin/env node', raw: true
})
]
,
externals: nodeModules
};
Note: I have significantly simplified the code example for brevity
Currently when i run the webpack command i get a folder webpack_bundle which contains an index.js file - the index.js file includes the dependencies config.js and read.js. However, what i would like is for the read.js dependency to be bundled into the index.js file but the config.js dependency to stay external in a separate file which gets required by the bundled webpack output. So the folder webpack_bundle should contain two files after running the webpack command - index.js and config.js. I have already tried to modify the externals by adding the following key value to the externals object config: './config.js' but this did not work. I also created an extra entrypoint by specifying config.js as the entrypoint but this also did not work. I can't figure this out and the webpack docs are not that clear on how to achieve this. Please help!
If you want your config in a separate bundle, you can create a split point, by importing dynamically your config.js file with require.ensure:
require.ensure([], function() {
let config = require('./config.js');
});
Your config will then be in a separate bundle.
Documentation about Code splitting (warning: Webpack 1.x is deprecated).
Documentation about Code Splitting (Webpack 2).
Edit:
If you don't want your config file to be bundled by Webpack, I think you can use IgnorePlugin:
module.exports = {
//...
plugins: [new webpack.IgnorePlugin(/^\.\/config\.js$/)]
}
And use copy-webpack-plugin to copy your config.js file.
Related
(webpack.config.js file content below)
I'm trying to make a webpack exclusion on node modules.
I found that using webpack-node-externals works for it but using that on my common config causes this other error:
Require is not defined on reflect-metadata - __webpack_require__ issue
So... I was wondering how can i exclude webpack bundling also on the browser side without getting any issue.
My webpack version: 3.11.0
webpack-config.js
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const AotPlugin = require('#ngtools/webpack').AotPlugin;
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
var nodeExternals = require('webpack-node-externals');
module.exports = (env) => {
// Configuration in common to both client-side and server-side bundles
const isDevBuild = !(env && env.prod);
const sharedConfig = {
//externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
stats: { modules: false },
context: __dirname,
resolve: { extensions: [ '.js', '.ts' ] },
output: {
filename: '[name].js',
publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{ test: /\.ts$/, use: isDevBuild ? ['awesome-typescript-loader?silent=true', 'angular2-template-loader', 'angular2-router-loader'] : '#ngtools/webpack' },
{ test: /\.html$/, use: 'html-loader?minimize=false' },
{ test: /\.css$/, use: [ 'to-string-loader', 'style-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
]
},
plugins: [new CheckerPlugin()]
};
// Configuration for client-side bundle suitable for running in browsers
const clientBundleOutputDir = './wwwroot/dist';
const clientBundleConfig = merge(sharedConfig, {
entry: { 'main-client': './ClientApp/boot.browser.ts' },
output: { path: path.join(__dirname, clientBundleOutputDir) },
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(),
new AotPlugin({
tsConfigPath: './tsconfig.json',
entryModule: path.join(__dirname, 'ClientApp/app/app.browser.module#AppModule'),
exclude: ['./**/*.server.ts']
})
])
});
// Configuration for server-side (prerendering) bundle suitable for running in Node
const serverBundleConfig = merge(sharedConfig, {
resolve: { mainFields: ['main'] },
entry: { 'main-server': './ClientApp/boot.server.ts' },
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./ClientApp/dist/vendor-manifest.json'),
sourceType: 'commonjs2',
name: './vendor'
})
].concat(isDevBuild ? [] : [
// Plugins that apply in production builds only
new AotPlugin({
tsConfigPath: './tsconfig.json',
entryModule: path.join(__dirname, 'ClientApp/app/app.server.module#AppModule'),
exclude: ['./**/*.browser.ts']
})
]),
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist')
},
target: 'node',
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder,
devtool: 'inline-source-map'
});
return [clientBundleConfig, serverBundleConfig];
};
GOT IT!
Before posting my solution, I'd like to thanks Aluan Haddad for his useful comment in my question above.
As suggested by Aluan, in fact, the problem was related to the need to use also a module loader, more than a module bundler.
So, the steps that I followed are these:
Installing requireJS ==> http://requirejs.org/docs/node.html
Removing externals: [nodeExternals()], // in order to ignore all modules in node_modules folder from my common webpack configuration and adding it under my server configuration (done before my question, but it's a really important step) [see webpack.config.js content in the question]
Adding target: 'node', before my externals point above, under my server side section (done before my question, but it's a really important step) [see webpack.config.js content in the question]
This makes sure that browser side keeps target:'web' (default target), and target becomes node just for the server.
launched webpack config vendor command manually from powershell webpack --config webpack.config.vendor.js
launched webpack config command manually from powershell webpack --config webpack.config.js
That worked for me! Hope It will works also for anyone else reading this question and encountering this issue!
I am trying to implement server side rendering using angular universal. With followed this post angular-4-universal-app-with-angular-cli and this cli-universal-demo project, I encountered a problem as below.
When node starts dist/server.js it shows an error:
(function (exports, require, module, __filename, __dirname)
{ export * from ‘./scn-filter-builder’
scn-filter-builder is my module. It's written in angular2/typescript and node.js doesn't understand it.
The question is that can I set to universal so it will compile packages from node_module to es5 by itself? Or I need to compile my component into es5?
So I ended up tackling something similar to this by compiling it with Webpack. I just added a webpack.config.js with the following:
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: {
server: './src/server.ts'
},
resolve: {
extensions: ['.ts', '.js']
},
target: 'node',
externals: [nodeExternals({
whitelist: [
/^ngx-bootstrap/
]
})],
node: {
__dirname: true
},
output: {
path: path.join(__dirname, 'server'),
filename: '[name].js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{ test: /\.ts$/, loader: 'ts-loader' }
]
}
}
Add the library that needs to be compiled in the nodeExternals -> whitelist area. In my case it was ngx-bootstrap. Then just run webpack to compile your file.
I have some troubles with webpack. I'm using ES6, ReactJS, Mobx and SASS. Here is my development config:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer');
var pathes = {
root: './src/main/webapp/WEB-INF/static',
entry: './src/main/javascript/client.js',
js: '/js/',
css: '/css/'
}
var extractSASS = new ExtractTextPlugin( path.join(pathes.css, 'main.css') );
var extractVendorCSS = new ExtractTextPlugin( path.join(pathes.css, 'vendor.css') );
module.exports = {
devtool: 'eval-source-map',
entry: pathes.entry,
output: {
path: pathes.root,
filename: path.join(pathes.js, 'app.js')
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loaders: [ 'babel' ]
},
{
test: /\.scss$/,
loader: extractSASS.extract([ 'css', 'postcss', 'sass' ])
},
{
test: /\.css$/,
loader: extractVendorCSS.extract([ 'css' ])
}
]
},
plugins: [
extractSASS,
extractVendorCSS,
new webpack.DefinePlugin({
DEVELOPMENT: true
})
],
postcss: function () {
return [ autoprefixer ];
}
};
All was good, but today I add interceptor for redirection to /index on server-side Spring boot application. I have no idea how this could break webpack, but he stopped to rebuild the bundle.
To run webpack I use this command:
webpack --progress --colors --watch --config ./configs/webpack.development.config.js
I don't use webpack-dev-server, because static files are served by embedded Tomcat (Spring boot).
In console webpack said that bundle was rebuilded, but bundle does not contains any changes.
An interesting detail is that if I change the bundle name from app.js to for example app1.js and re-run webpack by command above, webpack will take all changes and the bundle will be updated. After that webpack will automatically rebuild the bundle by for ane changes (because --watch).
Why webpack don't rebuild the bundle with old name app.js?
If your console shows that the files have been rebuilt and you're not seeing the changes, chances are the files are cached by your browser.
Try adding some kind of cache-busting parameter to wherever you are including them:
<script src="app.js?<% time.now() %>"></script>
This is fine for development, but for production, you might want to look at using the assets-webpack-plugin
I'd like to have structure like this
-Styles
--Main.scss
--SomeComponent.scss
-CompiledStyles
--Main.css
--SomeComponent.css
Actually I can only do this
-Styles
--Main.scss
--SomeComponent.scss
--All.scss (import all scss from file)
-CompiledStyles
--Main.css ( all css)
This is my webpack config
var Path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCSS2 = new ExtractTextPlugin('[name].css');
module.exports = {
devtool: 'eval',
entry: './Client/Styles/All.scss',
output: {
path: Path.join(__dirname, 'CompiledStyles'),
filename: 'page.js',
publicPath: '/CompiledStyles/'
},
module: {
loaders: [
{
test: /\.scss$/,
loader: extractCSS2.extract("style-loader", "css-loader!autoprefixer-loader!sass-loader")
},
{
//IMAGE LOADER
test: /\.(jpe?g|png|gif|svg)$/i,
loader: 'file-loader'
},
{
test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader?name=fonts/[name].[ext]'
}
]
},
plugins: [
extractCSS2
]
};
Is it possible to compile this scss files to single css files ?
I really don't know how to manage this case. I've tried to assign entry: './Client/Styles' but it occures error.
EDIT:
I solved this with gulp.
The idea of webpack is to put everything that is needed in some JavaScript-files. So it's the intention to not build a css-file for every css-file.
If you want to still use webpack, try this in your webpack config:
module.exports = {
// ...
entry: {
'Main': './Client/Styles/Main.scss',
'SomeComponents': './Client/Styles/SomeComponents.scss',
},
// ...
}
I have updated the answer after adamo94 noted that he used gulp, so just for everybody else some more information. To convert scss files you need a sass/scss-processor. You can easily call that processor with a single call but as you usually do more with your sources it's likely to use some further processing.
Usually you would use gulp or grunt. Those can be configured to build everything that you need. They have different pros and cons, there are also further tools, but those are probably the ones that you'd like to take a look.
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.