I'm trying to implement a solution for reading configurations from some file in my react app... don't know what is the best practice but I adapted the following way and tried implementing it:
1) under the root of my app (in parallel to webpack.config.js)
I created a file called: config.dev.json with this content:
{
"protocol" : "http",
"host" : "localhost",
"port" : "8080"
}
2) to webpack.config.js added my code (TODO part at the end):
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const rtlcss = require('rtlcss');
const webpack = require("webpack");
const useExternalCss =
process.env.CARBON_REACT_STORYBOOK_USE_EXTERNAL_CSS === 'true';
const useStyleSourceMap =
process.env.CARBON_REACT_STORYBOOK_USE_STYLE_SOURCEMAP === 'true';
const useRtl = process.env.CARBON_REACT_STORYBOOK_USE_RTL === 'true';
const styleLoaders = [
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: useStyleSourceMap,
},
},
{
loader: 'postcss-loader',
options: {
plugins: () => {
const autoPrefixer = require('autoprefixer')({
browsers: ['last 1 version', 'ie >= 11'],
});
return !useRtl ? [autoPrefixer] : [autoPrefixer, rtlcss];
},
sourceMap: useStyleSourceMap,
},
},
{
loader: 'sass-loader',
options: {
includePaths: [path.resolve(__dirname, '..', 'node_modules')],
data: `
$feature-flags: (
ui-shell: true,
);
`,
sourceMap: useStyleSourceMap,
},
},
];
module.exports = (baseConfig, env, defaultConfig) => {
defaultConfig.devtool = useStyleSourceMap ? 'source-map' : '';
defaultConfig.optimization = {
...defaultConfig.optimization,
minimizer: [
new TerserPlugin({
sourceMap: true,
terserOptions: {
mangle: false,
},
}),
],
};
defaultConfig.module.rules.push({
test: /-story\.jsx?$/,
loaders: [
{
loader: require.resolve('#storybook/addon-storysource/loader'),
options: {
prettierConfig: {
parser: 'babylon',
printWidth: 80,
tabWidth: 2,
bracketSpacing: true,
trailingComma: 'es5',
singleQuote: true,
},
},
},
],
enforce: 'pre',
});
defaultConfig.module.rules.push({
test: /\.scss$/,
sideEffects: true,
use: [
{ loader: useExternalCss ? MiniCssExtractPlugin.loader : 'style-loader' },
...styleLoaders,
],
});
if (useExternalCss) {
defaultConfig.plugins.push(
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
})
);
}
//TODO
if (!defaultConfig.resolve) {
defaultConfig.resolve = {};
}
if (!defaultConfig.resolve.alias) {
defaultConfig.resolve.alias = {};
}
defaultConfig.resolve.alias.Config = process.env.NODE_ENV === 'production'
? path.resolve('./config.prod.json')
: path.resolve('./config.dev.json');
return defaultConfig;
};
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development'),
'BASE_URL': JSON.stringify('http://localhost:3000/')
}
})
],
// externals: {
// 'Config': JSON.stringify(process.env.NODE_ENV === 'production' ? require('./config.prod.json') : require('./config.dev.json'))
// }
//
// // externals: {
// // 'Config': JSON.stringify(process.env.NODE_ENV === 'production' ? {
// // serverUrl: "http://test.com:8080"
// // } : {
// // serverUrl: "http://localhost:8080"
// // })
// // }
//
}
3) and tried to use it from some component that way:
let Config = require('Config')
but I'm getting:
./src/stores/RestService.js
Module not found: Can't resolve 'Config' in 'C:
If you want to setup configuration without webpack (e.g. when using create-react-app) this is how I'd suggest:
Create config folder (or name it however you want) and add your config files and index file:
config.dev.json
config.prod.json
index.js
And then inside your config/index.js file:
if (process.env.NODE_ENV === 'development') {
module.exports = require('./config.dev.json')
} else {
module.exports = require('./config.prod.json')
}
Use it with import config from './config';
why not use like this
at your package.json
"scripts": {
"develop": "PORT=8080 HOST=localhost PROTOCOL=http node ."
"production": "Your config here"
}
create a config/app.js
const config = process.env
module.export = {
port: config.PORT,
protocol: config.PROTOCOL,
host: config.HOST,
}
In your webpack ( actually, i don't know why you have to import config in your webpack and reexport it. if you want your jsx or js files able to read the PORT, HOST, and LOCALHOST, u can just follow until step 2, and u can freely get your config files in any your app.js files )
const config = require('./path/to/config/app.js')
module.exports = {
externals: {
config: config,
}
}
First you need the configuration file in your bundle, it's not an external (so we only need to remove the external part).
Then you need the config file to be resolved as a diffrent file depending on the environment (prod or dev, using resolve.alias).
Be carefull of the working directory too, either run webpack from the project's folder, or use the context configuration option.
Suggested webpack config (relevant part in the end):
module.exports = (baseConfig, env, defaultConfig) => {
defaultConfig.devtool = useStyleSourceMap ? 'source-map' : '';
defaultConfig.optimization = {
...defaultConfig.optimization,
minimizer: [
new TerserPlugin({
sourceMap: true,
terserOptions: {
mangle: false,
},
}),
],
};
defaultConfig.module.rules.push({
test: /-story\.jsx?$/,
loaders: [
{
loader: require.resolve('#storybook/addon-storysource/loader'),
options: {
prettierConfig: {
parser: 'babylon',
printWidth: 80,
tabWidth: 2,
bracketSpacing: true,
trailingComma: 'es5',
singleQuote: true,
},
},
},
],
enforce: 'pre',
});
defaultConfig.module.rules.push({
test: /\.scss$/,
sideEffects: true,
use: [
{ loader: useExternalCss ? MiniCssExtractPlugin.loader : 'style-loader' },
...styleLoaders,
],
});
defaultConfig.module.rules.push({
test: /\.json$/,
use: [
{ loader: useExternalCss ? MiniCssExtractPlugin.loader : 'style-loader' },
...styleLoaders,
],
});
if (useExternalCss) {
defaultConfig.plugins.push(
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
})
);
}
// ensure resolve alias present in the config
if (!defaultConfig.resolve) {
defaultConfig.resolve = {};
}
if (!defaultConfig.resolve.alias) {
defaultConfig.resolve.alias = {};
}
// resolve the alias to the right config file according to NODE_ENV
// you'll have to correctly set <relative path to your config>
defaultConfig.resolve.alias.Config = process.env.NODE_ENV === 'production'
? path.resolve(__dirname, '<relative path to your config>/config.prod.json')
: path.resolve(__dirname, '<relative path to your config>/config.dev.json');
return defaultConfig;
};
don't forget to remove this:
module.exports = {
externals: {
'Config': JSON.stringify(process.env.NODE_ENV === 'production' ? require('./config.prod.json') : require('./config.dev.json'))
}
// externals: {
// 'Config': JSON.stringify(process.env.NODE_ENV === 'production' ? {
// serverUrl: "http://test.test.com:8080"
// } : {
// serverUrl: "http://localhost:8080"
// })
// }
}
As it will prevent webpack from bundling the file.
You can use DefinePlugin to define setting config in webpack like this
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development'),
'BASE_URL': JSON.stringify('http://localhost:5000/')
}
})
],
Then simply use
process.env.BASE_URL
or
process.env.NODE_ENV
Related
I have upgraded #rails/webpacker from v4 to v5 (5.72.1, to be precise). While upgrading, I got following issue
ERROR in ./node_modules/croppie/croppie.css Module build failed (from
./node_modules/#rails/webpacker/node_modules/mini-css-extract-plugin/dist/loader.js):
TypeError: Cannot read property 'tap' of undefined
This is how I have setup my webpack config
const { environment } = require('#rails/webpacker');
const vue = require('./loaders/vue');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');
const customConfig = {
resolve: {
fallback: {
dgram: false,
fs: false,
net: false,
tls: false,
child_process: false,
},
},
entry: {
vendor: ['babel-polyfill', 'vue', 'moment', 'axios'],
},
};
environment.splitChunks((config) => {
console.log('config', environment);
return {
...config,
...{
optimization: {
splitChunks: { chunks: 'all', name: '~' },
runtimeChunk: true,
},
},
};
});
environment.config.delete('node.dgram');
environment.config.delete('node.fs');
environment.config.delete('node.net');
environment.config.delete('node.tls');
environment.config.delete('node.child_process');
environment.config.merge(customConfig);
environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin());
environment.loaders.append('vue', {
test: /\.vue$/,
loader: 'vue-loader',
});
// Comment this if you need case-sensitive-paths-plugin in local development.
if (process.env.RAILS_ENV === 'development') {
environment.plugins.delete('CaseSensitivePaths');
// Only add en.js locale for local development.
environment.plugins.append('moment', new webpack.ContextReplacementPlugin(/moment[/\\]locale/, /(en).js/));
}
environment.plugins.prepend('Environment', new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(process.env))));
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
})
);
const config = environment.toWebpackConfig();
config.resolve.alias = {
jquery: 'jquery/src/jquery',
};
let sassLoader = environment.loaders.get('sass').use.find(item => item.loader === 'sass-loader')
sassLoader = {
...sassLoader,
options: {
...sassLoader.options,
sassOptions: {
...sassLoader.options.sassOptions,
includePaths: ["./node_modules"],
}
}
}
let miniCssExtractPlugin = environment.plugins.get('MiniCssExtract')
console.log('miniCssExtractPlugin', miniCssExtractPlugin)
environment.loaders.append('vue', vue);
environment.config.merge({
optimization: {
minimize: false,
minimizer: [
new TerserPlugin({
test: /\.js(\?.*)?$/i,
}),
],
},
resolve: {
alias: {
app: path.resolve(__dirname, '../../app/'),
},
},
});
module.exports = environment
This is the logs
If I comment import 'croppie/croppie.css' in the js file where it is used, the error goes away where croppie is a third party library.
Not sure if this issue is only while importing third party css file.
I have imports in project like this one:
import { ytheme } from "./ytheme.js";
Why? Because:
https://www.typescriptlang.org/docs/handbook/2/modules.html#es-module-syntax
and Appending .js extension on relative import statements during Typescript compilation (ES6 modules) (the first answer)
Webpack tries to resolve it with an error:
Field 'browser' doesn't contain a valid alias configuration
<...>\src\client\components\ytheme.js.ts doesn't exist
Which obviously won't work. The correct path should be:
<...>\src\client\components\ytheme.ts
The question: How do I configure webpack to remove '.js' before appending '.ts' when resolving imports?
=========== Details ==========
webpack.config.js:
const path = require("path");
const fs = require("fs");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin").CleanWebpackPlugin;
const ReactRefreshWebpackPlugin = require("#pmmmwh/react-refresh-webpack-plugin");
const isDevelopment = process.env.NODE_ENV !== "production";
const pathes = (() => {
const proj = path.resolve(__dirname);
const projParts = proj.split(path.sep);
const projName = projParts[projParts.length - 1];
const root = path.resolve(__dirname, "");
return {
root,
proj,
projName,
resources: path.resolve(proj, "resources"),
bundles: path.resolve(proj, "lib/bundles", projName),
};
})();
for (let k in pathes) console.log(`pathes.${k} = ${pathes[k]}`);
const NODE_ENV = "development";
let BUILD_DATE = new Date();
BUILD_DATE.setTime(BUILD_DATE.getTime() + 3 * 60 * 60 * 1000);
BUILD_DATE = JSON.stringify(BUILD_DATE);
BUILD_DATE = BUILD_DATE.substr(1, 10) + " " + BUILD_DATE.substr(12, 8);
console.log("");
console.log("BUILD_DATE = " + BUILD_DATE);
console.log("");
let package_json;
let manifest_json;
package_json = JSON.parse(fs.readFileSync(path.resolve(pathes.root, "package.json"), { encoding: "utf-8" }));
manifest_json = JSON.parse(fs.readFileSync(path.resolve(pathes.resources, "manifest.json"), { encoding: "utf-8" }));
let tsconf = eval("(()=>(" + fs.readFileSync("tsconfig.json", "utf-8") + "))()");
let moduleAliases = {};
for (let k in tsconf.compilerOptions.paths) {
let v = tsconf.compilerOptions.paths[k];
moduleAliases[k] = path.resolve(pathes.root, "ts_out", v[0]);
}
let excludedModules = [
"fs",
"sql-prettier",
"prettier",
"express",
"socket.io",
"better-sqlite3",
"sqlite3",
"child_process",
];
module.exports = {
// TODO REMOVED ON 2020-13-11
// node: {
// fs: "empty",
// child_process: "empty",
// },
mode: "development",
entry: [path.resolve(pathes.proj, "src/client/indexSmall.tsx")],
devtool: "inline-source-map",
devServer: {
contentBase: "./resources",
hot: true,
},
resolve: {
fallback: {
crypto: false,
fs: false,
child_process: false,
path: false,
constants: false,
util: false,
assert: false,
stream: false,
// crypto: require.resolve("crypto-browserify"),
// fs:null,
},
// root: path.join(pathes.proj, 'js'),
// modulesDirectories: ['node_modules'],
extensions: ["", ".ts", ".tsx", ".js", ".jsx", ".json"],
alias: {
"react-dom": "#hot-loader/react-dom",
...moduleAliases,
},
},
output: {
path: pathes.bundles,
filename: "bundle.js",
},
module: {
rules: [
{
test: (modulePath0) => {
let modulePath = modulePath0.split(path.sep);
for (let excludedModule of excludedModules) if (modulePath.includes(excludedModule)) return true;
return false;
},
use: "null-loader",
},
{
test: /\.css$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
],
},
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader", // compiles Sass to CSS, using Node Sass by default
],
},
{
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
cacheDirectory: true,
babelrc: false,
presets: ["#babel/preset-typescript", "#babel/preset-react"],
plugins: [
["#babel/plugin-proposal-decorators", { legacy: true }],
"#babel/proposal-optional-chaining",
["#babel/proposal-class-properties", { legacy: true }],
"#babel/proposal-object-rest-spread",
// "react-hot-loader/babel",
[
"module-resolver",
{
root: ["./"],
alias: moduleAliases,
},
],
// "#babel/transform-modules-commonjs",
],
},
},
},
],
},
plugins: [
new webpack.DefinePlugin({
BROWSER: "true",
"process.env.BROWSER": "true",
NODE_ENV: JSON.stringify(NODE_ENV),
BUILD_DATE: JSON.stringify(BUILD_DATE),
// BASE_URL:JSON.stringify(private_js ? private_js.url : 'http://localhost')
}),
new CleanWebpackPlugin(),
// new webpack.NamedModulesPlugin(), // TODO REMOVED ON 2020-13-11
new HtmlWebpackPlugin({ title: manifest_json.name }),
isDevelopment && new webpack.HotModuleReplacementPlugin(),
isDevelopment && new ReactRefreshWebpackPlugin(),
],
// watchOptions : {
// aggregateTimeout : 300
// },
// "cheap-inline-module-source-map"
};
// console.log('YYAWEBPACK', JSON.stringify(module.exports.resolve.alias,null, "\t"));
The command I run dev server with:
webpack-cli serve --mode development --config webpack.frontend.config.js
Full error:
ERROR in ./src/client/indexSmall.tsx 7:0-48
Module not found: Error: Can't resolve './components/ytheme.js' in 'D:\b\Mine\GIT_Work\yatasks_one_api\src\client'
resolve './components/ytheme.js' in 'D:\b\Mine\GIT_Work\yatasks_one_api\src\client'
using description file: D:\b\Mine\GIT_Work\yatasks_one_api\package.json (relative path: ./src/client)
Field 'browser' doesn't contain a valid alias configuration
using description file: D:\b\Mine\GIT_Work\yatasks_one_api\package.json (relative path: ./src/client/components/ytheme.js)
Field 'browser' doesn't contain a valid alias configuration
D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js doesn't exist
.ts
Field 'browser' doesn't contain a valid alias configuration
D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.ts doesn't exist
.tsx
Field 'browser' doesn't contain a valid alias configuration
D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.tsx doesn't exist
.js
Field 'browser' doesn't contain a valid alias configuration
D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.js doesn't exist
.jsx
Field 'browser' doesn't contain a valid alias configuration
D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.jsx doesn't exist
.json
Field 'browser' doesn't contain a valid alias configuration
D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.json doesn't exist
as directory
D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js doesn't exist
webpack 5.41.1 compiled with 2 errors in 2120 ms
i 「wdm」: Failed to compile.
As a workaround the following snippet seems to work:
{ // webpack.config.cjs
plugins: [
new webpack.NormalModuleReplacementPlugin(/.*/, function (resource) {
const lowerCaseRequest = resource.request.toLowerCase();
if (
!lowerCaseRequest.includes("node_modules") &&
lowerCaseRequest.endsWith(".js") &&
lowerCaseRequest[0] === "." &&
resource.context.startsWith(path.resolve(__dirname))&&
!resource.context.toLowerCase().includes("node_modules")
) {
resource.request = resource.request.substr(0, resource.request.length - 3) + ".ts";
resource.request });
}
}),
...]
}
I am getting this error when logging into our dev site. This is a part of our migration from .NET framework 4.5.2 to 4.7.2. Though I do not think that has much to do with it. If we publish straight from VS, the page loads fine. If it uses our pipeline, or we did not clear our dirs beforehand, we get this error (in the console browser).
ie-polyfill_aurelia-bootstrapper:1 Uncaught ReferenceError:
webpack_require is not defined
at eval (ie-polyfill_aurelia-bootstrapper:1)
at Object.0 (xxxAppScripts?v=sRzkW2d1FsbC87Brht0ZS8CXZDQaGBaky9ddApOJOaY1:1)
at t (xxxAppScripts?v=sRzkW2d1FsbC87Brht0ZS8CXZDQaGBaky9ddApOJOaY1:1)
at xxxAppScripts?v=sRzkW2d1FsbC87Brht0ZS8CXZDQaGBaky9ddApOJOaY1:1
at xxxAppScripts?v=sRzkW2d1FsbC87Brht0ZS8CXZDQaGBaky9ddApOJOaY1:1
The process of our build should be exactly the same as building with NPM locally, and there are no errors given in the build process. Build is defined for both in the webpack.config.js as follows
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { AureliaPlugin, ModuleDependenciesPlugin } = require('aurelia-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const { ProvidePlugin, SourceMapDevToolPlugin } = require('webpack')
const { TsConfigPathsPlugin, CheckerPlugin } = require('awesome-typescript-loader');
const CleanWebpackPlugin = require('clean-webpack-plugin');
// config helpers:
const ensureArray = (config) => config && (Array.isArray(config) ? config : [config]) || []
const when = (condition, config, negativeConfig) =>
condition ? ensureArray(config) : ensureArray(negativeConfig)
// primary config:
const title = 'XXXXXX';
const outDir = path.resolve(__dirname, 'Scripts', 'pub');
const srcDir = path.resolve(__dirname, 'App');
const nodeModulesDir = path.resolve(__dirname, 'node_modules');
const baseUrl = '/';
var isDevBuild = true;
var dev;
if (process.env.NODE_ENV) {
dev = process.env.NODE_ENV.trim();
if (dev === "production") {
isDevBuild = true;
}
}
const cssRules = [
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: { plugins: () => [require('autoprefixer')({ browsers: ['last 2 versions'] })] }
},
'sass-loader'
];
module.exports = ({ production, server, extractCss, coverage } = {}) => ({
resolve: {
extensions: ['.ts', '.js'],
modules: [srcDir, 'node_modules'],
plugins: [
new TsConfigPathsPlugin(),
],
alias: {
// Enforce single aurelia-binding, to avoid v1/v2 duplication due to
// out-of-date dependencies on 3rd party aurelia plugins
'aurelia-binding': path.resolve(__dirname, 'node_modules/aurelia-binding'),
'aurelia-bootstrapper': path.resolve(__dirname, 'node_modules/aurelia-bootstrapper')
}
},
entry: {
app: ['./ie-polyfill', 'aurelia-bootstrapper'],
vendor: ['jquery'],
},
output: {
path: outDir,
publicPath: baseUrl,
filename: production ? '[name].[chunkhash].bundle.js' : '[name].[hash].bundle.js',
sourceMapFilename: production ? '[name].[chunkhash].bundle.map' : '[name].[hash].bundle.map',
chunkFilename: production ? '[chunkhash].chunk.js' : '[hash].chunk.js',
},
devServer: {
contentBase: baseUrl,
// serve index.html for all 404 (required for push-state)
historyApiFallback: '/',
},
module: {
rules: [
{
test: /\.css$/i,
issuer: [{ not: [{ test: /\.html$/i }] }],
use: extractCss ? ExtractTextPlugin.extract({
fallback: 'style-loader',
use: cssRules,
}) : ['style-loader', ...cssRules],
},
{
test: /\.css$/i,
issuer: [{ test: /\.html$/i }],
// CSS required in templates cannot be extracted safely
// because Aurelia would try to require it again in runtime
use: cssRules,
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader']
})
},
{ test: /\.html$/i, loader: 'html-loader' },
{ test: /\.ts$/i, loader: 'awesome-typescript-loader', exclude: nodeModulesDir },
{
test: require.resolve("jquery"),
use: [
{
loader: "expose-loader",
options: "$"
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
// required polyfills for non-evergreen browsers
new ProvidePlugin({
Map: 'core-js/es6/map',
WeakMap: 'core-js/es6/weak-map',
Promise: 'core-js/es6/promise',
regeneratorRuntime: 'regenerator-runtime' // to support await/async syntax
}),
new AureliaPlugin({
aureliaApp: 'main'
}),
new ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery',
'window.jQuery': 'jquery',
}),
new CheckerPlugin(),
new ExtractTextPlugin({
filename: production ? '[contenthash].css' : 'style-[id].css',
allChunks: true,
}),
].concat(isDevBuild ? [
new SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(outDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
new UglifyJsPlugin()
]),
})
There do seem to be a few times a similar question has been asked, but there has not been a solution that worked. Thanks for any help provided.
I'm experimenting with Vue2 and have a question on using lost-grid (http://lostgrid.org/) in my app. Lost-grid is a postcss grid-system and I've been able to use this numerous times in react apps with webpack2.
How can I use lost-grid i with vue-loader? I've installed 'lost' through npm, and tried different ways of adding the postcss loader. Nothing seems to work and the documentation isn't very helpful either.
Here is the business part of webpack.base.conf.js (as I undersrtand it, all the css loading is run through the vue-loader):
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: "pre",
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
...
vue-loader.conf.js looks like:
var utils = require('./utils')
var config = require('../config')
var isProduction = process.env.NODE_ENV === 'production'
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
})
}
utils.js looks like this:
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(''),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
Question now is... where do I put what? Any help would be greatly appreciated.
add the following lines to the vue-loader.config.js file in build/
postcss: [
require('autoprefixer')({
browsers: ['last 7 versions']
})
]
so it looks like this:
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap,
extract: isProduction
}),
postcss: [
require('autoprefixer')({
browsers: ['last 7 versions']
})
]
}
require('lost') should add to the postcss Array like above
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
In package.json have define, you can see https://github.com/ai/browserslist#config-file
My webpack.config.js file is as follows:
var path = require('path');
var webpack = require('webpack');
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
var autoprefixer = require('autoprefixer');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var ENV = process.env.npm_lifecycle_event;
var isTest = ENV === 'test' || ENV === 'test-watch';
var isProd = ENV === 'build';
module.exports = function makeWebpackConfig() {
var config = {};
if (isTest) {
config.devtool = 'inline-source-map';
} else if (isProd) {
config.devtool = 'source-map';
} else {
config.devtool = 'eval-source-map';
}
config.debug = !isProd || !isTest;
config.entry = isTest ? {} : {
'vendor': './src/vendor.ts',
'app': './src/bootstrap.ts' // our angular app
};
config.output = isTest ? {} : {
path: root('../edu_analytics_prod_front/dist'),
publicPath: isProd ? '/' : '/',
filename: isProd ? 'js/[name].[hash].js' : 'js/[name].js',
chunkFilename: isProd ? '[id].[hash].chunk.js' : '[id].chunk.js'
};
config.resolve = {
cache: !isTest,
root: root(),
extensions: ['', '.ts', '.js', '.json', '.css', '.scss', '.html'],
alias: {
'app': 'src/client',
'common': 'src/common'
}
};
config.module = {
preLoaders: isTest ? [] : [{test: /\.ts$/, loader: 'tslint'}],
loaders: [
// Support for .ts files.
{
test: /\.ts$/,
loader: 'ts',
query: {
'ignoreDiagnostics': [
2403, // 2403 -> Subsequent variable declarations
2300, // 2300 -> Duplicate identifier
2374, // 2374 -> Duplicate number index signature
2375, // 2375 -> Duplicate string index signature
2502 // 2502 -> Referenced directly or indirectly
]
},
exclude: [isTest ? /\.(e2e)\.ts$/ : /\.(spec|e2e)\.ts$/, /node_modules\/(?!(ng2-.+))/]
},
{test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, loader: 'file?name=fonts/[name].[hash].[ext]?'},
{test: /\.json$/, loader: 'json'},
{
test: /\.css$/,
exclude: root('src', 'client'),
loader: isTest ? 'null' : ExtractTextPlugin.extract('style', 'css?sourceMap!postcss')
},
// all css required in src/client files will be merged in js files
{test: /\.css$/, include: root('src', 'client'), loader: 'raw!postcss'},
{
test: /\.scss$/,
exclude: root('src', 'client'),
loader: isTest ? 'null' : ExtractTextPlugin.extract('style', 'css?sourceMap!postcss!sass')
},
{test: /\.scss$/, exclude: root('src', 'style'), loader: 'raw!postcss!sass'},
{test: /\.html$/, loader: 'raw'}
],
postLoaders: [],
noParse: [/.+angular2\/bundles\/.+/]
};
if (isTest) {
config.module.postLoaders.push({
test: /\.(js|ts)$/,
include: path.resolve('src'),
loader: 'istanbul-instrumenter-loader',
exclude: [/\.spec\.ts$/, /\.e2e\.ts$/, /node_modules/]
})
}
config.plugins = [
new webpack.DefinePlugin({
'process.env': {
ENV: JSON.stringify(ENV)
}
})
];
if (!isTest) {
config.plugins.push(
new CommonsChunkPlugin({
name: ['vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: './src/public/index.html',
inject: 'body',
chunksSortMode: packageSort(['polyfills', 'vendor', 'app'])
}),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false }
}),
new ExtractTextPlugin('css/[name].[hash].css', {disable: !isProd})
);
}
if (isProd) {
config.plugins.push(
new webpack.NoErrorsPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false }
}),
new CopyWebpackPlugin([{
from: root('src/public')
}])
);
}
config.postcss = [
autoprefixer({
browsers: ['last 2 version']
})
];
config.sassLoader = {
//includePaths: [path.resolve(__dirname, "node_modules/foundation-sites/scss")]
};
config.tslint = {
emitErrors: false,
failOnHint: false
};
config.devServer = {
contentBase: './src/public',
historyApiFallback: true,
stats: 'minimal' // none (or false), errors-only, minimal, normal (or true) and verbose
};
return config;
}();
function root(args) {
args = Array.prototype.slice.call(arguments, 0);
return path.join.apply(path, [__dirname].concat(args));
}
function rootNode(args) {
args = Array.prototype.slice.call(arguments, 0);
return root.apply(path, ['node_modules'].concat(args));
}
function packageSort(packages) {
var len = packages.length - 1;
var first = packages[0];
var last = packages[len];
return function sort(a, b) {
if (a.names[0] === first) {
return -1;
}
if (a.names[0] === last) {
return 1;
}
if (a.names[0] !== first && b.names[0] === last) {
return -1;
} else {
return 1;
}
}
}
When I'm running command like webpack / webpack -p
It is creating three files as follows:
But all three files has output as string and using eval function to deploy it and one file has very big size(7 MB) as follows.
I want simple JavaScript file without eval used inside it as all other common minification library works and I want to reduce size of vendor file as well.
Your config uses this configuration as default:
config.devtool = 'eval-source-map';
The fine manual states:
eval-source-map - Each module is executed with eval and a SourceMap is added as DataUrl to the eval.
If you don't want that, use another devtool option.
As for decreasing code size, you probably want to either disable the creation of a source map entirely (just don't set the devtool option) or have Webpack write the source map to a separate file (devtool : 'source-map' or devtool : 'cheap-source-map', AFAIK).
Also set the NODE_ENV environment variable to production if you want less code:
# if you're on a Unix-like OS:
env NODE_ENV=production webpack -p