Extract scss into multiple files using extract-text-webpack-plugin? - sass

My folder structure is like this
|
|-scss/
|-main1.scss
|-main2.scss
Is it possible to use extract-text-webpack-plugin to extract these two entry points two separate files?
Currently, I'm getting it as a single file.

If you specify the two entry points in your webpack config like so:
entry: {
main1: __dirname + '/src/main1.js',
main2: __dirname + '/src/main2.js',
},
ouput: {
path: __dirname,
filename: '[name].js'
}
I assume your main1.scss is imported in the main1.js file, and main2.scss is imported in main2.js.
You can then use the [name] placeholder on the extract-text-webpack-plugin, which should create a separate output file for each entry point:
plugins: [
new ExtractTextPlugin('[name].css')
]
This should output two separate css files for you: main1.css and main2.css
Hope this helps!

Related

Using terraform yamldecode to access multi level element

I have a yaml file (also used in a azure devops pipeline so needs to be in this format) which contains some settings I'd like to directly access from my terraform module.
The file looks something like:
variables:
- name: tenantsList
value: tenanta,tenantb
- name: unitName
value: canary
I'd like to have a module like this to access the settings but I can't see how to get to the bottom level:
locals {
settings = yamldecode(file("../settings.yml"))
}
module "infra" {
source = "../../../infra/terraform/"
unitname = local.settings.variables.unitName
}
But the terraform plan errors with this:
Error: Unsupported attribute
on canary.tf line 16, in module "infra":
16: unitname = local.settings.variables.unitName
|----------------
| local.settings.variables is tuple with 2 elements
This value does not have any attributes.
It seems like the main reason this is difficult is because this YAML file is representing what is logically a single map but is physically represented as a YAML list of maps.
When reading data from a separate file like this, I like to write an explicit expression to normalize it and optionally transform it for more convenient use in the rest of the Terraform module. In this case, it seems like having variables as a map would be the most useful representation as a Terraform value, so we can write a transformation expression like this:
locals {
raw_settings = yamldecode(file("${path.module}/../settings.yml"))
settings = {
variables = tomap({
for v in local.raw_settings.variables : v.name => v.value
})
}
}
The above uses a for expression to project the list of maps into a single map using the name values as the keys.
With the list of maps converted to a single map, you can then access it the way you originally tried:
module "infra" {
source = "../../../infra/terraform/"
unitname = local.settings.variables.unitName
}
If you were to output the transformed value of local.settings as YAML, it would look something like this, which is why accessing the map elements directly is now possible:
variables:
tenantsList: tenanta,tenantb
unitName: canary
This will work only if all of the name strings in your input are unique, because otherwise there would not be a unique map key for each element.
(Writing a normalization expression like this also doubles as some implicit validation for the shape of that YAML file: if variables were not a list or if the values were not all of the same type then Terraform would raise a type error evaluating that expression. Even if no transformation is required, I like to write out this sort of expression anyway because it serves as some documentation for what shape the YAML file is expected to have, rather than having to study all of the references to it throughout the rest of the configuration.)
With my multidecoder for YAML and JSON you are able to access multiple YAML and/or JSON files with their relative paths in one step.
Documentations can be found here:
Terraform Registry -
https://registry.terraform.io/modules/levmel/yaml_json/multidecoder/latest?tab=inputs
GitHub:
https://github.com/levmel/terraform-multidecoder-yaml_json
Usage
Place this module in the location where you need to access multiple different YAML and/or JSON files (different paths possible) and pass
your path/-s in the parameter filepaths which takes a set of strings of the relative paths of YAML and/or JSON files as an argument. You can change the module name if you want!
module "yaml_json_decoder" {
source = "levmel/yaml_json/multidecoder"
version = "0.2.1"
filepaths = ["routes/nsg_rules.yml", "failover/cosmosdb.json", "network/private_endpoints/*.yaml", "network/private_links/config_file.yml", "network/private_endpoints/*.yml", "pipeline/config/*.json"]
}
Patterns to access YAML and/or JSON files from relative paths:
To be able to access all YAML and/or JSON files in a folder entern your path as follows "folder/rest_of_folders/*.yaml", "folder/rest_of_folders/*.yml" or "folder/rest_of_folders/*.json".
To be able to access a specific YAML and/or a JSON file in a folder structure use this "folder/rest_of_folders/name_of_yaml.yaml", "folder/rest_of_folders/name_of_yaml.yml" or "folder/rest_of_folders/name_of_yaml.json"
If you like to select all YAML and/or JSON files within a folder, then you should use "*.yml", "*.yaml", "*.json" format notation. (see above in the USAGE section)
YAML delimiter support is available from version 0.1.0!
WARNING: Only the relative path must be specified. The path.root (it is included in the module by default) should not be passed, but everything after it.
Access YAML and JSON entries
Now you can access all entries within all the YAML and/or JSON files you've selected like that: "module.yaml_json_decoder.files.[name of your YAML or JSON file].entry". If the name of your YAML or JSON file is "name_of_your_config_file" then access it as follows "module.yaml_json_decoder.files.name_of_your_config_file.entry".
Example of multi YAML and JSON file accesses from different paths (directories)
first YAML file:
routes/nsg_rules.yml
rdp:
name: rdp
priority: 80
direction: Inbound
access: Allow
protocol: Tcp
source_port_range: "*"
destination_port_range: 3399
source_address_prefix: VirtualNetwork
destination_address_prefix: "*"
---
ssh:
name: ssh
priority: 70
direction: Inbound
access: Allow
protocol: Tcp
source_port_range: "*"
destination_port_range: 24
source_address_prefix: VirtualNetwork
destination_address_prefix: "*"
second YAML file:
services/logging/monitoring.yml
application_insights:
application_type: other
retention_in_days: 30
daily_data_cap_in_gb: 20
daily_data_cap_notifications_disabled: true
logs:
# Optional fields
- "AppMetrics"
- "AppAvailabilityResults"
- "AppEvents"
- "AppDependencies"
- "AppBrowserTimings"
- "AppExceptions"
- "AppExceptions"
- "AppPerformanceCounters"
- "AppRequests"
- "AppSystemEvents"
- "AppTraces"
first JSON file:
test/config/json_history.json
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
main.tf
module "yaml_json_multidecoder" {
source = "levmel/yaml_json/multidecoder"
version = "0.2.1"
filepaths = ["routes/nsg_rules.yml", "services/logging/monitoring.yml", test/config/*.json]
}
output "nsg_rules_entry" {
value = module.yaml_json_multidecoder.files.nsg_rules.aks.ssh.source_address_prefix
}
output "application_insights_entry" {
value = module.yaml_json_multidecoder.files.monitoring.application_insights.daily_data_cap_in_gb
}
output "json_history" {
value = module.yaml_json_multidecoder.files.json_history.glossary.title
}
Changes to Outputs:
nsg_rules_entry = "VirtualNetwork"
application_insights_entry = 20
json_history = "example glossary"

Namespace gets overwritten using rollup generated files

Rollup Version: 0.66.6
Operating System (or Browser): Mac, Chrome
Node Version: 10.13.0
Generate script using rollup with this configuration
const outputFileNamespace = "Foo";
const baseObject = {
input: 'js/modules/',
output: {
name: outputFileNamespace,
format: 'iife',
sourcemap: true,
banner: "/*Copyright text*/"
},
plugins: [(environment === PROD_ENV) && uglify()]
};
2. Generate multiple files using this configuration : js1.js , js2.js
3. Load these files in browser, namespace gets overriden
Expected Behavior
If we need to generate multiple output files with the common global namespace as "Foo" here, there should be some check in the generated file which checks for the existence of a global namespace
Actual Behavior
Namespace gets overwritten and the latter one js functions are available
Use a dot separated namespace for each build such as app.foo or use the option output.extend for extending instead of replacing the given namespace.

react-i18next cannot resolve key

I have a problem with react-i18next not resolving my keys, so everything I get as an output are the keys themself.
I had to embed my project as gui project to a VisualStudio solution. Running my original project works just fine, the solution project in contrast cannot resolve the key part of my translate function call.
t('user:KEY_CONSTANT') //output: KEY_CONSTANT
My i18n.config looks like this:
i18n
.use(XHR)
.init({
lng: i18nHelper.languageDetector(),
load: 'currentOnly',
fallbackLng: 'en-US',
backend: {
loadPath: 'i18n/{{lng}}/{{ns}}.json'
},
ns: ['admin', 'user'],
defaultNS: 'admin',
debug: false,
interpolation: {
escapeValue: false,
formatSeparator: ',',
format: function (vale, format, lng) {
if (format === 'uppercase') return value.toUpperCase();
return value;
}
}
});
When embedding the project in the solution, I had to change webpacks output folder, which I think is the actual reason of malfunctioning, but I can't find where exact the problem occurs. I tried changing the loadPath, but if thats the source of failure, I just didn't try it the right way :S
My project tree looks like:
Solution
|-gui
| |-src
| |-i18n
| |-de-DE(containing the german admin.json and user.json files)
| |-en-US(containing the english admin.json and user.json files)
| |-utils
| |-i18n.js
|-out
| |-prgFiles
| |-html
| |-i18n(contains same items as i18n under src)
In my old project, the webpack output was '/dist/' on the same level as src, in the solution, '../out/prgFiles/html'.
admin.json right now contains no keys at all, user.json contains the keys just like you'd expect:
{
"KEY_CONSTANT": "Actual string value"
}
As said, I tried around a bit with path changes, checked for translate, i18next and i18next-Provider beeing found and everythings fine. It just cant resolve KEY_CONSTANT to the actual value.
Do you have an idea what the problem might be?
set debug option to true in i18next init -> i bet you will get an error stating something like backendConnector failed to load namespace user...
make sure the clientside is able to load the translations (the webpack-dev server does a good job in doing so - but in production you will need to serve those file yourself)

Mix/version images in Laravel 5.4?

I want to use mix on a set of images. First I copy them:
mix.copy('resources/images', 'public/images');
Then version:
mix.version();
The above does nothing to the images.
I've also tried specifying the path:
mix.version('public/images/*');
But I get a no such file or directory error.
How can I version the images?
I know it's an old question, but for 2019 - laravel mix 4 you can use:
mix.copy('resources/images/*', 'public/images');
mix.version();
This will version all your copied files. DON'T use one of these:
mix.copy('resources/images/*', 'public/images/*');
mix.copy('resources/images/', 'public/images/*');
mix.copyDirectory('resources/images/*', 'public/images');
-> it will not version the files then.
The see the result, take a look in the public/mix-manifest.json:
"/favicon.ico": "/favicon.ico?id=ecb5fdce0172885513c8",
To use it in code, use the laravel mix helper method: mix();
<link rel="icon" type="image/x-icon" href="{{ mix('favicon.ico') }}" />
which will generate something like this:
<link rel="icon" type="image/x-icon" href="/favicon.ico?id=ecb5fdce0172885513c8" />
version() (without arguments) is not applied to files passed to copy() and copyDirectory().
If you'll look at the source of mix.version you'll see that it expands glob synchronously. But all laravel-mix operations such as copy and version are executed asynchronously. This means that public/images/* is empty because there are no files yet in public directory.
As a workaround you can list files in source directory (from which you copy files, for example resources), replace resources path segment with public and pass this list to version().
In my case I have various assets in resources directory so directory tree looks like:
- resources
| - css
| - fonts
| - images
| - js
| - less
I need to copy to public and version all these directories except less which I need to preprocess and also version.
This is like my webpack.mix.js looks like:
const mix = require('laravel-mix'),
glob = require('glob');
mix.disableNotifications();
const
directoriesToCopy = ['css', 'fonts', 'images', 'js'],
publicDir = 'public/',
publicCssDir = publicDir + 'css/',
resourcesDir = 'resources/',
resourcesLessDir = resourcesDir + 'less/',
lessFiles = glob.sync('**/*.less', {cwd: resourcesLessDir});
directoriesToCopy.forEach(d => mix.copyDirectory(resourcesDir + d, publicDir + d));
lessFiles.forEach(f => mix.less(resourcesLessDir + f, publicCssDir + f.slice(0, -'less'.length) + 'css'));
mix.version([].concat(...directoriesToCopy.map(d => glob.sync('**/*', {cwd: resourcesDir + d}).map(f => d + '/' + f))).map(f => publicDir + f));
Basically I use glob to recursively get a list of all files in each copied directory, replace resources with public in their paths and then pass list of all such files to mix.version.

Can you run multiple instances of webpack at once?

Let's say I have an array of components, that need to spit out their own source, as they wont always be included together, it needs to be it's own bundle. The idea is that there will eventually be 100's of components, and they can be cherry picked whenever.
However, when using webpack-stream with gulp, even though I'm dynamically registering the tasks, and that I can see they're running sequentially, it only runs one webpack stream by the looks of it, but seems to output it's bundle from the SECOND component, into the first components directory.
It's a pretty simple build process, it's an array of components like so:
var components = [
{'name : 'a', src : './foo/bar/entrya.js', dest : '/dir/a'},
{'name : 'b', src : './foo/bar/entryb.js', dest : '/dir/b'},
];
Relatively simple right? Then to register the tasks, it's something like this:
components.forEach(component => {
gulp.task(component.name, cb => {
function task(component) {
return gulp.src(component.src)
.pipe($.webpackStream(webpackConfig))
.pipe(component.dest(component.dest));
}
return task.apply(this, [component, cb]);
});
});
This is an incredibly dumbed down version of what I have, but it's pretty much the same thing, dynamically generates and then later on we run those tasks sequentially.
webpack-stream can handle multiple entry points and multiple builds per multiple entry points.
var gulp = require('gulp');
var webpack = require('webpack-stream');
gulp.task('build', function() {
return gulp.src(['src/entry.js']) // entry.js file doesn't need to exist
.pipe(webpack({
entry: {
a : __dirname + "/foo/bar/entrya.js",
b : __dirname + "/foo/bar/entryb.js"
},
output: {
filename: '[name].js'
}
}))
.pipe(gulp.dest('dir/'));
});
Your build is not running in parallel. you are just sequentially registering tasks. However you can run those tasks in parallel as child processes. One good option you can use is parallel-webpack.

Resources