shakapacker 6.0.0.rc.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.eslintignore +4 -0
- data/.eslintrc.js +14 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +18 -0
- data/.github/workflows/jest.yml +30 -0
- data/.github/workflows/js-lint.yml +31 -0
- data/.github/workflows/rubocop.yml +39 -0
- data/.github/workflows/ruby.yml +48 -0
- data/.gitignore +13 -0
- data/.node-version +1 -0
- data/.rubocop.yml +229 -0
- data/CHANGELOG.md +32 -0
- data/CONTRIBUTING.md +62 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +183 -0
- data/MIT-LICENSE +20 -0
- data/README.md +666 -0
- data/Rakefile +11 -0
- data/config/README.md +3 -0
- data/config/webpacker.yml +1 -0
- data/docs/customizing_babel_config.md +59 -0
- data/docs/deployment.md +116 -0
- data/docs/developing_webpacker.md +29 -0
- data/docs/troubleshooting.md +212 -0
- data/docs/v6_upgrade.md +158 -0
- data/gemfiles/Gemfile-rails-edge +12 -0
- data/gemfiles/Gemfile-rails.5.2.x +9 -0
- data/gemfiles/Gemfile-rails.6.0.x +9 -0
- data/gemfiles/Gemfile-rails.6.1.x +12 -0
- data/lib/install/application.js +15 -0
- data/lib/install/bin/webpacker +15 -0
- data/lib/install/bin/webpacker-dev-server +18 -0
- data/lib/install/bin/yarn +18 -0
- data/lib/install/binstubs.rb +4 -0
- data/lib/install/config/webpack/webpack.config.js +5 -0
- data/lib/install/config/webpacker.yml +64 -0
- data/lib/install/package.json +15 -0
- data/lib/install/template.rb +100 -0
- data/lib/shakapacker/utils/git_utils.rb +23 -0
- data/lib/shakapacker/utils/version_syntax_converter.rb +24 -0
- data/lib/tasks/webpacker/binstubs.rake +15 -0
- data/lib/tasks/webpacker/check_binstubs.rake +12 -0
- data/lib/tasks/webpacker/check_node.rake +31 -0
- data/lib/tasks/webpacker/check_yarn.rake +33 -0
- data/lib/tasks/webpacker/clean.rake +25 -0
- data/lib/tasks/webpacker/clobber.rake +20 -0
- data/lib/tasks/webpacker/compile.rake +45 -0
- data/lib/tasks/webpacker/info.rake +21 -0
- data/lib/tasks/webpacker/install.rake +17 -0
- data/lib/tasks/webpacker/verify_config.rake +14 -0
- data/lib/tasks/webpacker/verify_install.rake +4 -0
- data/lib/tasks/webpacker/yarn_install.rake +18 -0
- data/lib/tasks/webpacker.rake +19 -0
- data/lib/tasks/yarn.rake +38 -0
- data/lib/webpacker/commands.rb +79 -0
- data/lib/webpacker/compiler.rb +130 -0
- data/lib/webpacker/configuration.rb +111 -0
- data/lib/webpacker/dev_server.rb +72 -0
- data/lib/webpacker/dev_server_proxy.rb +33 -0
- data/lib/webpacker/dev_server_runner.rb +96 -0
- data/lib/webpacker/env.rb +43 -0
- data/lib/webpacker/helper.rb +161 -0
- data/lib/webpacker/instance.rb +41 -0
- data/lib/webpacker/manifest.rb +120 -0
- data/lib/webpacker/railtie.rb +63 -0
- data/lib/webpacker/runner.rb +23 -0
- data/lib/webpacker/version.rb +4 -0
- data/lib/webpacker/webpack_runner.rb +58 -0
- data/lib/webpacker.rb +46 -0
- data/package/__tests__/config.js +34 -0
- data/package/__tests__/dev_server.js +45 -0
- data/package/__tests__/development.js +35 -0
- data/package/__tests__/env.js +58 -0
- data/package/__tests__/index.js +9 -0
- data/package/__tests__/production.js +29 -0
- data/package/__tests__/staging.js +30 -0
- data/package/__tests__/test.js +25 -0
- data/package/babel/preset.js +41 -0
- data/package/config.js +32 -0
- data/package/configPath.js +3 -0
- data/package/dev_server.js +20 -0
- data/package/env.js +27 -0
- data/package/environments/__tests__/base.js +69 -0
- data/package/environments/base.js +116 -0
- data/package/environments/development.js +55 -0
- data/package/environments/production.js +79 -0
- data/package/environments/test.js +3 -0
- data/package/index.js +33 -0
- data/package/inliningCss.js +7 -0
- data/package/rules/babel.js +30 -0
- data/package/rules/coffee.js +6 -0
- data/package/rules/css.js +3 -0
- data/package/rules/erb.js +15 -0
- data/package/rules/file.js +23 -0
- data/package/rules/index.js +18 -0
- data/package/rules/less.js +22 -0
- data/package/rules/raw.js +5 -0
- data/package/rules/sass.js +16 -0
- data/package/rules/stylus.js +26 -0
- data/package/utils/get_style_rule.js +37 -0
- data/package/utils/helpers.js +51 -0
- data/package.json +71 -0
- data/rakelib/release.rake +57 -0
- data/test/command_test.rb +109 -0
- data/test/compiler_test.rb +68 -0
- data/test/configuration_test.rb +78 -0
- data/test/dev_server_runner_test.rb +81 -0
- data/test/dev_server_test.rb +47 -0
- data/test/engine_rake_tasks_test.rb +39 -0
- data/test/env_test.rb +23 -0
- data/test/helper_test.rb +159 -0
- data/test/manifest_test.rb +89 -0
- data/test/mounted_app/Rakefile +4 -0
- data/test/mounted_app/test/dummy/Rakefile +3 -0
- data/test/mounted_app/test/dummy/bin/rails +3 -0
- data/test/mounted_app/test/dummy/bin/rake +3 -0
- data/test/mounted_app/test/dummy/config/application.rb +10 -0
- data/test/mounted_app/test/dummy/config/environment.rb +3 -0
- data/test/mounted_app/test/dummy/config/webpacker.yml +75 -0
- data/test/mounted_app/test/dummy/config.ru +5 -0
- data/test/mounted_app/test/dummy/package.json +7 -0
- data/test/rake_tasks_test.rb +71 -0
- data/test/test_app/Rakefile +3 -0
- data/test/test_app/app/packs/entrypoints/application.js +10 -0
- data/test/test_app/app/packs/entrypoints/multi_entry.css +4 -0
- data/test/test_app/app/packs/entrypoints/multi_entry.js +4 -0
- data/test/test_app/bin/webpacker +14 -0
- data/test/test_app/bin/webpacker-dev-server +14 -0
- data/test/test_app/config/application.rb +11 -0
- data/test/test_app/config/environment.rb +4 -0
- data/test/test_app/config/initializers/inspect_autoload_paths.rb +1 -0
- data/test/test_app/config/webpack/webpack.config.js +0 -0
- data/test/test_app/config/webpacker.yml +77 -0
- data/test/test_app/config/webpacker_other_location.yml +79 -0
- data/test/test_app/config/webpacker_public_root.yml +18 -0
- data/test/test_app/config.ru +5 -0
- data/test/test_app/package.json +13 -0
- data/test/test_app/public/packs/manifest.json +50 -0
- data/test/test_app/some.config.js +0 -0
- data/test/test_app/yarn.lock +11 -0
- data/test/test_helper.rb +33 -0
- data/test/webpack_runner_test.rb +57 -0
- data/test/webpacker_test.rb +34 -0
- data/webpacker.gemspec +31 -0
- data/yarn.lock +4029 -0
- metadata +331 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
/* global test expect, describe */
|
2
|
+
|
3
|
+
const { chdirTestApp, chdirCwd } = require('../utils/helpers')
|
4
|
+
|
5
|
+
chdirTestApp()
|
6
|
+
|
7
|
+
describe('Env', () => {
|
8
|
+
beforeEach(() => jest.resetModules())
|
9
|
+
afterAll(chdirCwd)
|
10
|
+
|
11
|
+
test('with NODE_ENV and RAILS_ENV set to development', () => {
|
12
|
+
process.env.RAILS_ENV = 'development'
|
13
|
+
process.env.NODE_ENV = 'development'
|
14
|
+
expect(require('../env')).toEqual({
|
15
|
+
railsEnv: 'development',
|
16
|
+
nodeEnv: 'development',
|
17
|
+
isProduction: false,
|
18
|
+
isDevelopment: true,
|
19
|
+
runningWebpackDevServer: false
|
20
|
+
})
|
21
|
+
})
|
22
|
+
|
23
|
+
test('with undefined NODE_ENV and RAILS_ENV set to development', () => {
|
24
|
+
process.env.RAILS_ENV = 'development'
|
25
|
+
delete process.env.NODE_ENV
|
26
|
+
expect(require('../env')).toEqual({
|
27
|
+
railsEnv: 'development',
|
28
|
+
nodeEnv: 'production',
|
29
|
+
isProduction: true,
|
30
|
+
isDevelopment: false,
|
31
|
+
runningWebpackDevServer: false
|
32
|
+
})
|
33
|
+
})
|
34
|
+
|
35
|
+
test('with undefined NODE_ENV and RAILS_ENV', () => {
|
36
|
+
delete process.env.NODE_ENV
|
37
|
+
delete process.env.RAILS_ENV
|
38
|
+
expect(require('../env')).toEqual({
|
39
|
+
railsEnv: 'production',
|
40
|
+
nodeEnv: 'production',
|
41
|
+
isProduction: true,
|
42
|
+
isDevelopment: false,
|
43
|
+
runningWebpackDevServer: false
|
44
|
+
})
|
45
|
+
})
|
46
|
+
|
47
|
+
test('with a non-standard environment', () => {
|
48
|
+
process.env.RAILS_ENV = 'staging'
|
49
|
+
process.env.NODE_ENV = 'staging'
|
50
|
+
expect(require('../env')).toEqual({
|
51
|
+
railsEnv: 'staging',
|
52
|
+
nodeEnv: 'production',
|
53
|
+
isProduction: true,
|
54
|
+
isDevelopment: false,
|
55
|
+
runningWebpackDevServer: false
|
56
|
+
})
|
57
|
+
})
|
58
|
+
})
|
@@ -0,0 +1,9 @@
|
|
1
|
+
const index = require('../index')
|
2
|
+
|
3
|
+
describe('index', () => {
|
4
|
+
test('exports webpack-merge v5 functions', () => {
|
5
|
+
expect(index.merge).toBeInstanceOf(Function)
|
6
|
+
expect(index.mergeWithRules).toBeInstanceOf(Function)
|
7
|
+
expect(index.mergeWithCustomize).toBeInstanceOf(Function)
|
8
|
+
})
|
9
|
+
})
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/* test expect, describe, afterAll, beforeEach */
|
2
|
+
|
3
|
+
const { resolve } = require('path')
|
4
|
+
const { chdirTestApp, chdirCwd } = require('../utils/helpers')
|
5
|
+
|
6
|
+
chdirTestApp()
|
7
|
+
|
8
|
+
describe('Production environment', () => {
|
9
|
+
afterAll(chdirCwd)
|
10
|
+
|
11
|
+
describe('webpackConfig', () => {
|
12
|
+
beforeEach(() => jest.resetModules())
|
13
|
+
|
14
|
+
test('should use production config and environment', () => {
|
15
|
+
process.env.RAILS_ENV = 'production'
|
16
|
+
process.env.NODE_ENV = 'production'
|
17
|
+
|
18
|
+
const { webpackConfig } = require('../index')
|
19
|
+
|
20
|
+
expect(webpackConfig.output.path).toEqual(resolve('public', 'packs'))
|
21
|
+
expect(webpackConfig.output.publicPath).toEqual('/packs/')
|
22
|
+
|
23
|
+
expect(webpackConfig).toMatchObject({
|
24
|
+
devtool: 'source-map',
|
25
|
+
stats: 'normal'
|
26
|
+
})
|
27
|
+
})
|
28
|
+
})
|
29
|
+
})
|
@@ -0,0 +1,30 @@
|
|
1
|
+
/* test expect, describe, afterAll, beforeEach */
|
2
|
+
|
3
|
+
const { resolve } = require('path')
|
4
|
+
const { chdirTestApp, chdirCwd } = require('../utils/helpers')
|
5
|
+
|
6
|
+
chdirTestApp()
|
7
|
+
|
8
|
+
describe('Custom environment', () => {
|
9
|
+
afterAll(chdirCwd)
|
10
|
+
|
11
|
+
describe('webpackConfig', () => {
|
12
|
+
beforeEach(() => jest.resetModules())
|
13
|
+
|
14
|
+
test('should use staging config and default production environment', () => {
|
15
|
+
process.env.RAILS_ENV = 'staging'
|
16
|
+
delete process.env.NODE_ENV
|
17
|
+
|
18
|
+
const { webpackConfig } = require('../index')
|
19
|
+
|
20
|
+
expect(webpackConfig.output.path).toEqual(
|
21
|
+
resolve('public', 'packs-staging')
|
22
|
+
)
|
23
|
+
expect(webpackConfig.output.publicPath).toEqual('/packs-staging/')
|
24
|
+
expect(webpackConfig).toMatchObject({
|
25
|
+
devtool: 'source-map',
|
26
|
+
stats: 'normal'
|
27
|
+
})
|
28
|
+
})
|
29
|
+
})
|
30
|
+
})
|
@@ -0,0 +1,25 @@
|
|
1
|
+
/* test expect, describe, afterAll, beforeEach */
|
2
|
+
|
3
|
+
const { resolve } = require('path')
|
4
|
+
const { chdirTestApp, chdirCwd } = require('../utils/helpers')
|
5
|
+
|
6
|
+
chdirTestApp()
|
7
|
+
|
8
|
+
describe('Test environment', () => {
|
9
|
+
afterAll(chdirCwd)
|
10
|
+
|
11
|
+
describe('toWebpackConfig', () => {
|
12
|
+
beforeEach(() => jest.resetModules())
|
13
|
+
|
14
|
+
test('should use test config and production environment', () => {
|
15
|
+
process.env.RAILS_ENV = 'test'
|
16
|
+
process.env.NODE_ENV = 'test'
|
17
|
+
|
18
|
+
const { webpackConfig } = require('../index')
|
19
|
+
|
20
|
+
expect(webpackConfig.output.path).toEqual(resolve('public', 'packs-test'))
|
21
|
+
expect(webpackConfig.output.publicPath).toEqual('/packs-test/')
|
22
|
+
expect(webpackConfig.devServer).toEqual(undefined)
|
23
|
+
})
|
24
|
+
})
|
25
|
+
})
|
@@ -0,0 +1,41 @@
|
|
1
|
+
const { moduleExists } = require('@shakacode/shakapacker')
|
2
|
+
|
3
|
+
module.exports = function config(api) {
|
4
|
+
const validEnv = ['development', 'test', 'production']
|
5
|
+
const currentEnv = api.env()
|
6
|
+
const isDevelopmentEnv = api.env('development')
|
7
|
+
const isProductionEnv = api.env('production')
|
8
|
+
const isTestEnv = api.env('test')
|
9
|
+
|
10
|
+
if (!validEnv.includes(currentEnv)) {
|
11
|
+
throw new Error(
|
12
|
+
`Please specify a valid NODE_ENV or BABEL_ENV environment variable. Valid values are "development", "test", and "production". Instead, received: "${JSON.stringify(
|
13
|
+
currentEnv
|
14
|
+
)}".`
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
18
|
+
return {
|
19
|
+
presets: [
|
20
|
+
isTestEnv && ['@babel/preset-env', { targets: { node: 'current' } }],
|
21
|
+
(isProductionEnv || isDevelopmentEnv) && [
|
22
|
+
'@babel/preset-env',
|
23
|
+
{
|
24
|
+
useBuiltIns: 'entry',
|
25
|
+
corejs: '3.8',
|
26
|
+
modules: 'auto',
|
27
|
+
bugfixes: true,
|
28
|
+
loose: true,
|
29
|
+
exclude: ['transform-typeof-symbol']
|
30
|
+
}
|
31
|
+
],
|
32
|
+
moduleExists('@babel/preset-typescript') && [
|
33
|
+
'@babel/preset-typescript',
|
34
|
+
{ allExtensions: true, isTSX: true }
|
35
|
+
]
|
36
|
+
].filter(Boolean),
|
37
|
+
plugins: [
|
38
|
+
['@babel/plugin-transform-runtime', { helpers: false }]
|
39
|
+
].filter(Boolean)
|
40
|
+
}
|
41
|
+
}
|
data/package/config.js
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
const { resolve } = require('path')
|
2
|
+
const { load } = require('js-yaml')
|
3
|
+
const { readFileSync } = require('fs')
|
4
|
+
const { merge } = require('webpack-merge')
|
5
|
+
const { ensureTrailingSlash } = require('./utils/helpers')
|
6
|
+
const { railsEnv } = require('./env')
|
7
|
+
const configPath = require('./configPath')
|
8
|
+
|
9
|
+
const defaultConfigPath = require.resolve('../lib/install/config/webpacker.yml')
|
10
|
+
|
11
|
+
const getDefaultConfig = () => {
|
12
|
+
const defaultConfig = load(readFileSync(defaultConfigPath), 'utf8')
|
13
|
+
return defaultConfig[railsEnv] || defaultConfig.production
|
14
|
+
}
|
15
|
+
|
16
|
+
const defaults = getDefaultConfig()
|
17
|
+
const app = load(readFileSync(configPath), 'utf8')[railsEnv]
|
18
|
+
|
19
|
+
const config = merge(defaults, app)
|
20
|
+
config.outputPath = resolve(config.public_root_path, config.public_output_path)
|
21
|
+
|
22
|
+
// Ensure that the publicPath includes our asset host so dynamic imports
|
23
|
+
// (code-splitting chunks and static assets) load from the CDN instead of a relative path.
|
24
|
+
const getPublicPath = () => {
|
25
|
+
const rootUrl = ensureTrailingSlash(process.env.WEBPACKER_ASSET_HOST || '/')
|
26
|
+
return `${rootUrl}${config.public_output_path}/`
|
27
|
+
}
|
28
|
+
|
29
|
+
config.publicPath = getPublicPath()
|
30
|
+
config.publicPathWithoutCDN = `/${config.public_output_path}/`
|
31
|
+
|
32
|
+
module.exports = config
|
@@ -0,0 +1,20 @@
|
|
1
|
+
const { isBoolean } = require('./utils/helpers')
|
2
|
+
const config = require('./config')
|
3
|
+
|
4
|
+
const fetch = (key) => {
|
5
|
+
const value = process.env[key]
|
6
|
+
return isBoolean(value) ? JSON.parse(value) : value
|
7
|
+
}
|
8
|
+
|
9
|
+
const devServerConfig = config.dev_server
|
10
|
+
|
11
|
+
if (devServerConfig) {
|
12
|
+
const envPrefix = config.dev_server.env_prefix || 'WEBPACKER_DEV_SERVER'
|
13
|
+
|
14
|
+
Object.keys(devServerConfig).forEach((key) => {
|
15
|
+
const envValue = fetch(`${envPrefix}_${key.toUpperCase()}`)
|
16
|
+
if (envValue !== undefined) devServerConfig[key] = envValue
|
17
|
+
})
|
18
|
+
}
|
19
|
+
|
20
|
+
module.exports = devServerConfig || {}
|
data/package/env.js
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
const { load } = require('js-yaml')
|
2
|
+
const { readFileSync } = require('fs')
|
3
|
+
|
4
|
+
const NODE_ENVIRONMENTS = ['development', 'production', 'test']
|
5
|
+
const DEFAULT = 'production'
|
6
|
+
const configPath = require('./configPath')
|
7
|
+
|
8
|
+
const railsEnv = process.env.RAILS_ENV
|
9
|
+
const rawNodeEnv = process.env.NODE_ENV
|
10
|
+
const nodeEnv
|
11
|
+
= rawNodeEnv && NODE_ENVIRONMENTS.includes(rawNodeEnv) ? rawNodeEnv : DEFAULT
|
12
|
+
const isProduction = nodeEnv === 'production'
|
13
|
+
const isDevelopment = nodeEnv === 'development'
|
14
|
+
|
15
|
+
const config = load(readFileSync(configPath), 'utf8')
|
16
|
+
const availableEnvironments = Object.keys(config).join('|')
|
17
|
+
const regex = new RegExp(`^(${availableEnvironments})$`, 'g')
|
18
|
+
|
19
|
+
const runningWebpackDevServer = process.env.WEBPACK_SERVE === 'true'
|
20
|
+
|
21
|
+
module.exports = {
|
22
|
+
railsEnv: railsEnv && railsEnv.match(regex) ? railsEnv : DEFAULT,
|
23
|
+
nodeEnv,
|
24
|
+
isProduction,
|
25
|
+
isDevelopment,
|
26
|
+
runningWebpackDevServer
|
27
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
/* global test expect, describe, afterAll, beforeEach */
|
2
|
+
|
3
|
+
// environment.js expects to find config/webpacker.yml and resolved modules from
|
4
|
+
// the root of a Rails project
|
5
|
+
|
6
|
+
const { chdirTestApp, chdirCwd } = require('../../utils/helpers')
|
7
|
+
|
8
|
+
chdirTestApp()
|
9
|
+
|
10
|
+
const { resolve } = require('path')
|
11
|
+
const rules = require('../../rules')
|
12
|
+
const baseConfig = require('../base')
|
13
|
+
|
14
|
+
describe('Base config', () => {
|
15
|
+
afterAll(chdirCwd)
|
16
|
+
|
17
|
+
describe('config', () => {
|
18
|
+
test('should return entry', () => {
|
19
|
+
expect(baseConfig.entry.application).toEqual(
|
20
|
+
resolve('app', 'packs', 'entrypoints', 'application.js')
|
21
|
+
)
|
22
|
+
})
|
23
|
+
|
24
|
+
test('should return multi file entry points', () => {
|
25
|
+
expect(baseConfig.entry.multi_entry.sort()).toEqual([
|
26
|
+
resolve('app', 'packs', 'entrypoints', 'multi_entry.css'),
|
27
|
+
resolve('app', 'packs', 'entrypoints', 'multi_entry.js')
|
28
|
+
])
|
29
|
+
})
|
30
|
+
|
31
|
+
test('should return output', () => {
|
32
|
+
expect(baseConfig.output.filename).toEqual('js/[name].js')
|
33
|
+
expect(baseConfig.output.chunkFilename).toEqual(
|
34
|
+
'js/[name].chunk.js'
|
35
|
+
)
|
36
|
+
})
|
37
|
+
|
38
|
+
test('should return default loader rules for each file in config/loaders', () => {
|
39
|
+
const defaultRules = Object.keys(rules)
|
40
|
+
const configRules = baseConfig.module.rules
|
41
|
+
|
42
|
+
expect(defaultRules.length).toEqual(3)
|
43
|
+
expect(configRules.length).toEqual(3)
|
44
|
+
})
|
45
|
+
|
46
|
+
test('should return default plugins', () => {
|
47
|
+
expect(baseConfig.plugins.length).toEqual(2)
|
48
|
+
})
|
49
|
+
|
50
|
+
test('should return default resolveLoader', () => {
|
51
|
+
expect(baseConfig.resolveLoader.modules).toEqual(['node_modules'])
|
52
|
+
})
|
53
|
+
|
54
|
+
test('should return default resolve.modules with additions', () => {
|
55
|
+
expect(baseConfig.resolve.modules).toEqual([
|
56
|
+
resolve('app', 'packs'),
|
57
|
+
resolve('app/assets'),
|
58
|
+
resolve('/etc/yarn'),
|
59
|
+
resolve('some.config.js'),
|
60
|
+
resolve('app/elm'),
|
61
|
+
'node_modules'
|
62
|
+
])
|
63
|
+
})
|
64
|
+
|
65
|
+
test('returns plugins property as Array', () => {
|
66
|
+
expect(baseConfig.plugins).toBeInstanceOf(Array)
|
67
|
+
})
|
68
|
+
})
|
69
|
+
})
|
@@ -0,0 +1,116 @@
|
|
1
|
+
/* eslint global-require: 0 */
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
3
|
+
|
4
|
+
const { basename, dirname, join, relative, resolve } = require('path')
|
5
|
+
const extname = require('path-complete-extname')
|
6
|
+
const PnpWebpackPlugin = require('pnp-webpack-plugin')
|
7
|
+
const { sync: globSync } = require('glob')
|
8
|
+
const WebpackAssetsManifest = require('webpack-assets-manifest')
|
9
|
+
const webpack = require('webpack')
|
10
|
+
const rules = require('../rules')
|
11
|
+
const { isProduction } = require('../env')
|
12
|
+
const config = require('../config')
|
13
|
+
const { moduleExists } = require('../utils/helpers')
|
14
|
+
|
15
|
+
const getEntryObject = () => {
|
16
|
+
const entries = {}
|
17
|
+
const rootPath = join(config.source_path, config.source_entry_path)
|
18
|
+
|
19
|
+
globSync(`${rootPath}/*.*`).forEach((path) => {
|
20
|
+
const namespace = relative(join(rootPath), dirname(path))
|
21
|
+
const name = join(namespace, basename(path, extname(path)))
|
22
|
+
let assetPaths = resolve(path)
|
23
|
+
|
24
|
+
// Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
|
25
|
+
// Transforms the config object value to an array with all values under the same name
|
26
|
+
let previousPaths = entries[name]
|
27
|
+
if (previousPaths) {
|
28
|
+
previousPaths = Array.isArray(previousPaths)
|
29
|
+
? previousPaths
|
30
|
+
: [previousPaths]
|
31
|
+
previousPaths.push(assetPaths)
|
32
|
+
assetPaths = previousPaths
|
33
|
+
}
|
34
|
+
|
35
|
+
entries[name] = assetPaths
|
36
|
+
})
|
37
|
+
|
38
|
+
return entries
|
39
|
+
}
|
40
|
+
|
41
|
+
const getModulePaths = () => {
|
42
|
+
const result = [resolve(config.source_path)]
|
43
|
+
|
44
|
+
if (config.additional_paths) {
|
45
|
+
config.additional_paths.forEach((path) => result.push(resolve(path)))
|
46
|
+
}
|
47
|
+
result.push('node_modules')
|
48
|
+
|
49
|
+
return result
|
50
|
+
}
|
51
|
+
|
52
|
+
const getPlugins = () => {
|
53
|
+
const plugins = [
|
54
|
+
new webpack.EnvironmentPlugin(process.env),
|
55
|
+
new WebpackAssetsManifest({
|
56
|
+
entrypoints: true,
|
57
|
+
writeToDisk: true,
|
58
|
+
output: 'manifest.json',
|
59
|
+
entrypointsUseAssets: true,
|
60
|
+
publicPath: true
|
61
|
+
})
|
62
|
+
]
|
63
|
+
|
64
|
+
if (moduleExists('css-loader') && moduleExists('mini-css-extract-plugin')) {
|
65
|
+
const hash = isProduction ? '-[contenthash:8]' : ''
|
66
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
67
|
+
plugins.push(
|
68
|
+
new MiniCssExtractPlugin({
|
69
|
+
filename: `css/[name]${hash}.css`,
|
70
|
+
chunkFilename: `css/[id]${hash}.css`
|
71
|
+
})
|
72
|
+
)
|
73
|
+
}
|
74
|
+
|
75
|
+
return plugins
|
76
|
+
}
|
77
|
+
|
78
|
+
// Don't use contentHash except for production for performance
|
79
|
+
// https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
|
80
|
+
const hash = isProduction ? '-[contenthash]' : ''
|
81
|
+
module.exports = {
|
82
|
+
mode: 'production',
|
83
|
+
output: {
|
84
|
+
filename: `js/[name]${hash}.js`,
|
85
|
+
chunkFilename: `js/[name]${hash}.chunk.js`,
|
86
|
+
|
87
|
+
// https://webpack.js.org/configuration/output/#outputhotupdatechunkfilename
|
88
|
+
hotUpdateChunkFilename: 'js/[id].[fullhash].hot-update.js',
|
89
|
+
path: config.outputPath,
|
90
|
+
publicPath: config.publicPath
|
91
|
+
},
|
92
|
+
entry: getEntryObject(),
|
93
|
+
resolve: {
|
94
|
+
extensions: ['.js', '.jsx', '.mjs', '.ts', '.tsx', '.coffee'],
|
95
|
+
modules: getModulePaths(),
|
96
|
+
plugins: [PnpWebpackPlugin]
|
97
|
+
},
|
98
|
+
|
99
|
+
plugins: getPlugins(),
|
100
|
+
|
101
|
+
resolveLoader: {
|
102
|
+
modules: ['node_modules'],
|
103
|
+
plugins: [PnpWebpackPlugin.moduleLoader(module)]
|
104
|
+
},
|
105
|
+
|
106
|
+
optimization: {
|
107
|
+
splitChunks: { chunks: 'all' },
|
108
|
+
|
109
|
+
runtimeChunk: 'single'
|
110
|
+
},
|
111
|
+
|
112
|
+
module: {
|
113
|
+
strictExportPresence: true,
|
114
|
+
rules
|
115
|
+
}
|
116
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
const { merge } = require('webpack-merge')
|
2
|
+
|
3
|
+
const baseConfig = require('./base')
|
4
|
+
const devServer = require('../dev_server')
|
5
|
+
const { runningWebpackDevServer } = require('../env')
|
6
|
+
|
7
|
+
const { outputPath: contentBase, publicPath } = require('../config')
|
8
|
+
|
9
|
+
let devConfig = {
|
10
|
+
mode: 'development',
|
11
|
+
devtool: 'cheap-module-source-map'
|
12
|
+
}
|
13
|
+
|
14
|
+
if (runningWebpackDevServer) {
|
15
|
+
const liveReload = devServer.live_reload !== undefined ? devServer.live_reload : !devServer.hmr
|
16
|
+
|
17
|
+
const devServerConfig = {
|
18
|
+
devMiddleware: {
|
19
|
+
publicPath
|
20
|
+
},
|
21
|
+
compress: devServer.compress,
|
22
|
+
allowedHosts: devServer.allowed_hosts,
|
23
|
+
host: devServer.host,
|
24
|
+
port: devServer.port,
|
25
|
+
https: devServer.https,
|
26
|
+
hot: devServer.hmr,
|
27
|
+
liveReload,
|
28
|
+
historyApiFallback: { disableDotRule: true },
|
29
|
+
headers: devServer.headers,
|
30
|
+
static: {
|
31
|
+
publicPath: contentBase
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
if (devServer.static) {
|
36
|
+
devServerConfig.static = { ...devServerConfig.static, ...devServer.static }
|
37
|
+
}
|
38
|
+
|
39
|
+
if (devServer.client) {
|
40
|
+
devServerConfig.client = devServer.client
|
41
|
+
}
|
42
|
+
|
43
|
+
devConfig = merge(devConfig, {
|
44
|
+
stats: {
|
45
|
+
colors: true,
|
46
|
+
entrypoints: false,
|
47
|
+
errorDetails: true,
|
48
|
+
modules: false,
|
49
|
+
moduleTrace: false
|
50
|
+
},
|
51
|
+
devServer: devServerConfig
|
52
|
+
})
|
53
|
+
}
|
54
|
+
|
55
|
+
module.exports = merge(baseConfig, devConfig)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
/* eslint global-require: 0 */
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
3
|
+
|
4
|
+
const { merge } = require('webpack-merge')
|
5
|
+
const CompressionPlugin = require('compression-webpack-plugin')
|
6
|
+
const TerserPlugin = require('terser-webpack-plugin')
|
7
|
+
const baseConfig = require('./base')
|
8
|
+
const { moduleExists } = require('../utils/helpers')
|
9
|
+
|
10
|
+
const getPlugins = () => {
|
11
|
+
const plugins = []
|
12
|
+
|
13
|
+
plugins.push(
|
14
|
+
new CompressionPlugin({
|
15
|
+
filename: '[path][base].gz[query]',
|
16
|
+
algorithm: 'gzip',
|
17
|
+
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
|
18
|
+
})
|
19
|
+
)
|
20
|
+
|
21
|
+
if ('brotli' in process.versions) {
|
22
|
+
plugins.push(
|
23
|
+
new CompressionPlugin({
|
24
|
+
filename: '[path][base].br[query]',
|
25
|
+
algorithm: 'brotliCompress',
|
26
|
+
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
|
27
|
+
})
|
28
|
+
)
|
29
|
+
}
|
30
|
+
|
31
|
+
return plugins
|
32
|
+
}
|
33
|
+
|
34
|
+
const tryCssMinimizer = () => {
|
35
|
+
if (
|
36
|
+
moduleExists('css-loader') &&
|
37
|
+
moduleExists('css-minimizer-webpack-plugin')
|
38
|
+
) {
|
39
|
+
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
|
40
|
+
return new CssMinimizerPlugin()
|
41
|
+
}
|
42
|
+
|
43
|
+
return null
|
44
|
+
}
|
45
|
+
|
46
|
+
const productionConfig = {
|
47
|
+
devtool: 'source-map',
|
48
|
+
stats: 'normal',
|
49
|
+
bail: true,
|
50
|
+
plugins: getPlugins(),
|
51
|
+
optimization: {
|
52
|
+
minimizer: [
|
53
|
+
tryCssMinimizer(),
|
54
|
+
new TerserPlugin({
|
55
|
+
parallel: Number.parseInt(process.env.WEBPACKER_PARALLEL, 10) || true,
|
56
|
+
terserOptions: {
|
57
|
+
parse: {
|
58
|
+
// Let terser parse ecma 8 code but always output
|
59
|
+
// ES5 compliant code for older browsers
|
60
|
+
ecma: 8
|
61
|
+
},
|
62
|
+
compress: {
|
63
|
+
ecma: 5,
|
64
|
+
warnings: false,
|
65
|
+
comparisons: false
|
66
|
+
},
|
67
|
+
mangle: { safari10: true },
|
68
|
+
output: {
|
69
|
+
ecma: 5,
|
70
|
+
comments: false,
|
71
|
+
ascii_only: true
|
72
|
+
}
|
73
|
+
}
|
74
|
+
})
|
75
|
+
].filter(Boolean)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
module.exports = merge(baseConfig, productionConfig)
|
data/package/index.js
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
/* eslint global-require: 0 */
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
3
|
+
|
4
|
+
const webpackMerge = require('webpack-merge')
|
5
|
+
const { resolve } = require('path')
|
6
|
+
const { existsSync } = require('fs')
|
7
|
+
const baseConfig = require('./environments/base')
|
8
|
+
const rules = require('./rules')
|
9
|
+
const config = require('./config')
|
10
|
+
const devServer = require('./dev_server')
|
11
|
+
const env = require('./env')
|
12
|
+
const { moduleExists, canProcess } = require('./utils/helpers')
|
13
|
+
const inliningCss = require('./inliningCss')
|
14
|
+
|
15
|
+
const webpackConfig = () => {
|
16
|
+
const { nodeEnv } = env
|
17
|
+
const path = resolve(__dirname, 'environments', `${nodeEnv}.js`)
|
18
|
+
const environmentConfig = existsSync(path) ? require(path) : baseConfig
|
19
|
+
return environmentConfig
|
20
|
+
}
|
21
|
+
|
22
|
+
module.exports = {
|
23
|
+
config,
|
24
|
+
devServer,
|
25
|
+
webpackConfig: webpackConfig(),
|
26
|
+
baseConfig,
|
27
|
+
env,
|
28
|
+
rules,
|
29
|
+
moduleExists,
|
30
|
+
canProcess,
|
31
|
+
inliningCss,
|
32
|
+
...webpackMerge
|
33
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
const { resolve } = require('path')
|
2
|
+
const { realpathSync } = require('fs')
|
3
|
+
|
4
|
+
const {
|
5
|
+
source_path: sourcePath,
|
6
|
+
additional_paths: additionalPaths
|
7
|
+
} = require('../config')
|
8
|
+
const { isProduction } = require('../env')
|
9
|
+
|
10
|
+
module.exports = {
|
11
|
+
test: /\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/,
|
12
|
+
include: [sourcePath, ...additionalPaths].map((p) => {
|
13
|
+
try {
|
14
|
+
return realpathSync(p)
|
15
|
+
} catch (e) {
|
16
|
+
return resolve(p)
|
17
|
+
}
|
18
|
+
}),
|
19
|
+
exclude: /node_modules/,
|
20
|
+
use: [
|
21
|
+
{
|
22
|
+
loader: require.resolve('babel-loader'),
|
23
|
+
options: {
|
24
|
+
cacheDirectory: true,
|
25
|
+
cacheCompression: isProduction,
|
26
|
+
compact: isProduction
|
27
|
+
}
|
28
|
+
}
|
29
|
+
]
|
30
|
+
}
|